/*
Theme Name:   DJ Joyeros Child
Theme URI:    https://dyj-joyeros.com
Description:  Tema hijo de Storefront para D&J Joyeros (joyería de lujo, Bogotá). Contiene toda la maquetación custom y las plantillas de WooCommerce sobrescritas del sitio.
Author:       D&J Joyeros
Template:     storefront
Version:      1.0.245
Text Domain:  dj-joyeros-child
*/

:root {
	--djj-dark: #0A1A22;
	--djj-teal: #0E3A43;
	--djj-cream: #F4EFE7;
	--djj-gold: #C9A25D;
}

body {
	font-family: 'Poppins', sans-serif;
}

/* Esquinas rectas en TODAS las imágenes del sitio — Storefront (tema
   padre) trae un `img { border-radius: 3px; }` propio en su `style.css`
   (confirmado inspeccionando qué regla real gana con
   `CSSStyleSheet.cssRules` en el navegador), nunca anulado hasta ahora —
   por eso todas las fotos del sitio (hero, catálogo, catálogo por Sexo,
   vista previa de productos, carrito, ficha de producto) tenían esa
   esquina redondeada de 3px sin que ningún selector propio de este
   archivo la pusiera. Mismo selector genérico `img` (misma
   especificidad), pero este archivo se carga DESPUÉS del de Storefront,
   así que gana por orden de cascada sin necesitar `!important` ni un
   selector más específico. */
img {
	border-radius: 0;
}

h1, h2, h3 {
	font-family: 'Cormorant Garamond', serif;
	font-weight: 500;
}

/* ==================== HEADER (reskin de Storefront) ==================== */

/* position:sticky no funciona aquí: Storefront pone "overflow-x:hidden" en <body>,
   y por el acoplamiento de ejes de overflow en CSS eso convierte overflow-y en "auto"
   automáticamente, lo que invalida el contexto sticky. "fixed" no depende de eso —
   a cambio, hay que compensar con padding-top en el body para que el contenido no
   quede tapado detrás del header (ver más abajo, "espacio para el header fijo"). */
#masthead.site-header {
	/* Azul Noche oficial (`--djj-dark`, #0A1A22) — el logo en sí se
	   recoloreó (script Python + Pillow, reemplazo por distancia de color
	   contra el fondo real del PNG, sin tocar el diamante ni el texto
	   dorado) para que su propio fondo pasara de #011422 (el tono real del
	   archivo original, distinto del oficial) a este mismo #0A1A22 — así
	   logo y header coinciden exactamente Y ambos quedan en el color
	   oficial de marca, sin necesitar un valor "a medida" acá. */
	background-color: var(--djj-dark);
	border-bottom: 1px solid rgba(201, 162, 93, 0.35);
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 99;
	/* Storefront trae ~26px de padding propio arriba/abajo por defecto;
	   sin anularlo, el alto real del header no coincide con logo + margen. */
	padding: 0;
}

/* ⚠️ Bug real, encontrado ajustando el alto del header — mismo patrón que
   ya se vio varias veces en este archivo (`.storefront-sorting`,
   `ul.products`): Storefront aplica un clearfix nativo a `.col-full`
   (`::before`/`::after` con `content:""; display:table`), pensado para su
   layout original con floats. Bajo el `display:flex` que este tema le pone
   a `#masthead .col-full` (más abajo), esos pseudo-elementos se cuentan
   como dos ítems flex más — y con `align-items:center`, terminaban
   estirando el alto de la línea flex bastante más allá de lo que medía
   `.site-branding` (el ítem real más alto), corriendo nav/carrito hacia
   abajo del centro real y dejando el header más alto de lo que su propio
   contenido justificaba. Se anulan, acotado a `#masthead .col-full`
   específicamente (no `.col-full` a secas, para no tocar otros usos de esa
   clase en el resto del sitio que sí puedan necesitar el clearfix real). */
#masthead .col-full::before,
#masthead .col-full::after {
	content: none;
	display: none;
}

/* A pedido explícito y repetido del usuario: sin contorno de foco visible en
   NINGÚN elemento del sitio (ni el nativo del navegador, ni una versión
   recoloreada) — regla global, no una lista de selectores puntuales (el
   enfoque anterior, elemento por elemento, se quedaba corto cada vez que
   aparecía en algo nuevo: menú, carrito, tarjeta de categoría, "Volver al
   catálogo", el logo del header...). Cubre todo lo enfocable, incluyendo
   elementos nativos de WooCommerce/Storefront no restyleados por el tema. */
a:focus,
button:focus,
input:focus,
select:focus,
textarea:focus,
[tabindex]:focus {
	outline: none;
}

/* Espacio para el header fijo, para que no tape el contenido de la página.
   ⚠️ Bug real, causa del "espacio en blanco debajo del header" reportado
   por el usuario — estos valores (91px/116px) quedaron desactualizados
   desde que se cambió el logo por uno de proporción mucho más ancha (esta
   misma sesión): el nuevo logo, con `width:auto; max-height` puesto, topa
   antes con el `max-width` nativo de Storefront para la imagen del logo
   (sin calificar por este tema) que con nuestro propio `max-height` —
   termina renderizando más bajo de lo que esos números asumían, y de paso
   se encontró un segundo bug apilado (`.site-branding` con
   `margin-bottom:1.41575em` nativo de Storefront, invisible a
   `getBoundingClientRect()`, que además inflaba el alto real del header en
   escritorio — ver `#masthead .site-branding` más abajo). Con ambos
   corregidos, el alto REAL del header quedó bien por debajo de estos
   valores viejos, dejando ese espacio en blanco vacío. Recalculados en
   vivo tras los fixes + el +5px pedido para el alto del header (logo +
   12.5px arriba/abajo en móvil, +10.5px en escritorio). */
/* ⚠️ Bug real, encontrado tras el ajuste de arriba — línea horizontal
   blanca visible justo debajo del header, reportada por el usuario.
   Causa: el alto real del header es un valor FRACCIONARIO (73.24px móvil,
   ver arriba), pero se había redondeado hacia ARRIBA a 74px acá — a
   propósito, para garantizar que el padding nunca quedara corto y tapara
   contenido detrás del header (`position:fixed`, fuera del flujo normal).
   Ese redondeo dejaba un hueco de ~0.76px donde se asomaba el blanco de
   fondo del body, entre el borde inferior real del header y donde
   arrancaba el contenido — imperceptible en la mayoría de fondos, pero muy
   visible contra el header oscuro. Se usa el valor fraccionario exacto en
   vez de redondear — mismo patrón que el resto de este archivo (9px, 47.15px,
   etc., ver 10.4e/10.4i) — así no queda ni un sub-píxel de sobra ni de menos. */
body {
	padding-top: 73.24px; /* alto real del header móvil, medido en vivo */
}

@media (min-width: 768px) {
	body {
		padding-top: 73.75px; /* alto real del header en escritorio, medido en vivo */
	}
}

/* Header fusionado en un solo contenedor (ver functions.php): logo a la
   izquierda, nav + carrito agrupados a la derecha vía margin-right:auto
   en site-branding, en vez de dos filas apiladas/superpuestas. */
@media (min-width: 768px) {
	#masthead .col-full {
		display: flex;
		align-items: center;
		flex-wrap: wrap;
		gap: 16px 32px;
	}

	/* Storefront fuerza width:100% en .main-navigation (mobile-first);
	   sin anularlo, cada hijo ocupa toda la fila y todo se apila igual
	   que antes de fusionar el header. */
	#masthead .site-branding,
	#masthead .main-navigation,
	#site-header-cart.site-header-cart {
		width: auto;
	}

	#masthead .site-branding {
		margin-right: auto;
	}
}

/* ==================== HEADER ESCRITORIO: logo centrado + menú desplegable (2026-08-30) ====================
   A pedido del usuario: una sola fila (ya era así, ver bloque de arriba),
   logo centrado, carrito a la derecha, y el menú de escritorio pasa a ser
   desplegable igual que en móvil — mismo mecanismo, no uno nuevo.

   Por qué es seguro reusar el mecanismo de móvil sin tocar su bloque
   (@media max-width:767px, sin modificar): el JS que abre/cierra el menú
   (navigation.js de Storefront) no depende del ancho de pantalla en
   absoluto — agrega un listener de click al botón que alterna la clase
   `.toggled` en `#site-navigation`, sin ningún chequeo de viewport. Lo que
   hace que hoy solo funcione en móvil es puro CSS: Storefront trae, sin
   media query, `.primary-navigation{display:block}` y
   `.handheld-navigation,.menu-toggle{display:none}` — y ESE bloque sí está
   envuelto en un media query de escritorio en su propio style.css. Acá se
   invierten esas 2 reglas, pero solo dentro de min-width:768px: en móvil,
   las reglas nativas (sin media query, "mobile-first") siguen exactamente
   igual que antes, intactas.

   Logo, botón y carrito pasan a `position:absolute` (mismo criterio que ya
   usa el header móvil, 7.4) — si el contenedor del menú crece de alto al
   desplegarse, un centrado por flexbox normal correría los 3 elementos
   hacia abajo junto con ese crecimiento (exactamente el bug ya documentado
   y resuelto en móvil). Con posición fija, ninguno se mueve, esté el menú
   abierto o cerrado. */
@media (min-width: 768px) {
	/* Sin esto, el fondo oscuro del header colapsaría a 0 de alto: al sacar
	   los 3 elementos reales del flujo (position:absolute), `.col-full` ya
	   no tiene contenido normal que le dé altura, y `#masthead` (el que
	   pinta el fondo) se ajusta al alto de su contenido. */
	#masthead .col-full {
		min-height: 73.75px; /* mismo alto real medido del header, ver 7.5 */
	}

	/* Logo centrado horizontal Y verticalmente respecto al header completo
	   (no a .col-full) — coincide en la práctica porque .col-full ya está
	   centrado en el viewport, pero anclar contra #masthead (ya
	   position:fixed, sirve de contenedor de referencia sin agregarle
	   position:relative a .col-full) es más directo. */
	#masthead .site-branding {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		margin: 0;
	}

	/* Menú de escritorio → desplegable: se apaga el menú inline nativo y se
	   prende el mecanismo de acordeón que ya usa móvil (mismo `.menu>ul`
	   con `max-height:0` → `9999px` al agregar `.toggled` en #site-navigation,
	   sin CSS nuevo para esa parte — ya existe, sin media query).

	   ⚠️ `.main-navigation` sigue siendo un hijo flex normal de `.col-full`
	   (no está en la fila absoluta de logo/botón/carrito) — al desplegarse,
	   su contenido arrancaba en la misma banda vertical que el logo/botón
	   (y=0), superpuesto con ellos, en vez de aparecer DEBAJO del header.

	   ⚠️ El `position:absolute` va en `.handheld-navigation` (el panel en
	   sí), NO en `.main-navigation` (su contenedor) — primer intento real:
	   ponerlo en `.main-navigation` convertía a ESE contenedor en el
	   "contexto de posicionamiento" para el botón de menú, que vive
	   adentro y también es `position:absolute` — el botón pasó a
	   posicionarse contra `.main-navigation` (ahora en `top:73.75px`) en
	   vez de contra `#masthead`, y se corrió visualmente debajo del header
	   entero. `.main-navigation` se deja tal cual (flex item normal,
	   `width:auto` de la regla original) — con `.primary-navigation`
	   oculto y `.handheld-navigation` ya fuera del flujo, no le queda
	   contenido real que lo infle, así que no afecta nada más. */
	#masthead .primary-navigation {
		display: none;
	}
	#masthead .handheld-navigation {
		display: block;
		position: absolute;
		top: 73.75px;
		left: 0;
		right: 0;
		width: 100%;
		background: var(--djj-dark);
		/* Mismo padding lateral que usan el resto de las secciones del sitio
		   (clamp(20-48px)) — sin esto, "Catálogo" (el primer ítem) quedaba
		   cortado: el `<ul class="menu">` nativo de Storefront trae
		   `margin-left:-16px` (confirmado con getComputedStyle, sin relación
		   con nada que este tema haya tocado), y el panel en sí arranca en
		   `left:0` (borde real del viewport, no el inset de `.col-full`) —
		   sin padding, el primer ítem terminaba con su borde izquierdo en
		   -16px real, parcialmente fuera de pantalla. */
		padding: 0 clamp(20px, 5vw, 48px);
		box-sizing: border-box;
		/* Línea dorada al pie del panel, a pedido del usuario — en móvil ya
		   se ve sola, porque ahí `.handheld-navigation` no es `position:absolute`
		   y el `<header>` real CRECE de alto al desplegarse, arrastrando con
		   él su propio `border-bottom` nativo (`#masthead.site-header`, sin
		   media query, `rgba(201,162,93,0.35)`) hasta el borde inferior real
		   del menú abierto. En escritorio ese mismo borde se quedó fijo en
		   `top:73.75px` (el alto ORIGINAL del header, ver `min-height` más
		   arriba) porque este panel es `position:absolute` — el panel, con
		   su propio fondo sólido, termina tapando esa línea en vez de
		   mostrarla en su borde real. Mismo color/opacidad que el borde
		   nativo del header, para que se vea como una continuación de él. */
		border-bottom: 1px solid rgba(201, 162, 93, 0.35);
	}
	/* Neutraliza el margin-left:-16px nativo directamente — el padding de
	   arriba ya daba suficiente aire, pero anular la causa real (no solo
	   compensarla) es más robusto si el margen nativo cambia de valor en
	   una actualización futura de Storefront. */
	#masthead .handheld-navigation .menu {
		margin-left: 0;
	}

	/* ⚠️ Bug real — con `.toggled` puesto, el panel seguía en `max-height:0`
	   (no se desplegaba). Storefront trae, sin media query,
	   `.main-navigation.toggled .handheld-navigation{max-height:9999px}`
	   (debería ganar por especificidad contra su propia regla base
	   `.handheld-navigation{max-height:0}`) — pero el propio bloque de
	   escritorio de Storefront agrega, en la MISMA lista de selectores que
	   oculta el botón, `.main-navigation.toggled .handheld-navigation` con
	   `display:none` (pensado para ocultar el panel en escritorio incluso
	   si algún día quedara "toggled" desde móvil) — no toca `max-height`
	   directamente, pero confirma que Storefront nunca esperó que este
	   panel se desplegara en escritorio. Definir `max-height` acá también
	   (con especificidad más alta que cualquiera de las reglas nativas
	   involucradas) resuelve el problema sin depender de adivinar cuál
	   ganaba exactamente. */
	#masthead .main-navigation.toggled .handheld-navigation {
		max-height: 9999px;
	}

	/* Botón de menú, junto al carrito, a la derecha (decisión del usuario).
	   Mismo tamaño/color/técnica que el botón de móvil (7.4), solo que acá
	   fijo a la derecha en vez de a la izquierda del carrito. */
	#masthead .menu-toggle {
		display: block;
		position: absolute;
		top: 16.875px; /* (73.75px alto real del header - 40px del ícono) / 2 */
		right: 96px; /* ancho del carrito (40px) + su offset (40px, ver más abajo) + 16px de separación */
		margin: 0;
		float: none;
		max-width: none;
		width: 40px;
		height: 40px;
		padding: 0;
		border: none;
		background: transparent;
		box-shadow: none;
	}
	#masthead .menu-toggle::before,
	#masthead .menu-toggle::after,
	#masthead .menu-toggle span::before {
		left: 50%;
		/* +21% en total sobre los 16px originales (dos pedidos de +10%
		   consecutivos, el segundo solo en escritorio) — 16 × 1.1 × 1.1 =
		   19.36px. `margin-left` a la mitad (-9.68px) para que la barra se
		   quede centrada. Móvil se queda en el primer +10% (17.6px, ver el
		   bloque de móvil más abajo). */
		margin-left: -9.68px;
		width: 19.36px;
		background-color: var(--djj-gold) !important;
	}
	/* Oculta visualmente el texto "Menú" sin quitarlo para lectores de pantalla — mismo patrón que móvil. */
	#masthead .menu-toggle span {
		position: absolute;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
		border: 0;
	}

	/* Carrito a la derecha, con el mismo `top` fijo que el botón — mismo
	   motivo: no debe moverse cuando el menú se despliega. El ícono en sí
	   (22px dorado, contador) ya está resuelto por el bloque de escritorio
	   existente más abajo (7.10) — esto solo fija la posición del wrapper.
	   `right:40px` (antes 20px) — 20px extra a pedido del usuario, separa
	   el carrito del borde y corre botón+carrito hacia la izquierda juntos
	   (el logo no se mueve, sigue centrado por su cuenta). */
	#site-header-cart.site-header-cart {
		position: absolute;
		top: 16.875px;
		right: 40px;
		margin: 0;
		height: 40px;
		display: flex;
		align-items: center;
	}
}

/* ⚠️ Bug real, causa verdadera del desajuste de alto del header (no el
   clearfix de arriba, que se descartó al no cambiar nada) — Storefront trae
   `.site-branding{margin-bottom:1.41575em}` (~22.65px) nativo, pensado para
   separar el logo del resto del contenido en su layout original apilado.
   `getBoundingClientRect()` no incluye márgenes, así que ese espacio quedó
   invisible en las mediciones (branding parecía medir 68px) hasta revisar
   `getComputedStyle` directo — confirmado: 22.652px reales. Con
   `align-items:center` en el flex del header, ese margen SÍ cuenta para el
   alto de la línea flex, empujando el alto real de `.col-full` a 90.73px
   en vez de los 68.08px que el logo+padding realmente necesitan, y
   corriendo nav/carrito hacia abajo del centro visual real. Se anula acá. */
#masthead .site-branding {
	padding: 10.5px 0; /* +2.5px arriba/abajo, a pedido del usuario (alto del header +5px en escritorio) */
	margin-bottom: 0;
}

#masthead .custom-logo {
	max-height: 90px;
	width: auto;
}

#masthead .site-search {
	display: none;
}

#masthead .main-navigation .primary-navigation .menu > li > a,
#masthead .main-navigation .handheld-navigation .menu > li > a {
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	color: var(--djj-cream);
}

/* ⚠️ Bug real, encontrado al agregar "Postventa" como 6º ítem del menú —
   el header entero (`#masthead`, `position:fixed`) trae `flex-wrap:wrap`
   nativo de Storefront en `.col-full`, con `column-gap:32px` entre
   logo/nav/carrito. Con 5 ítems sobraba espacio; con 6, el carrito ya no
   entraba en el resto de la primera fila (quedaban ~29px libres, el
   carrito necesita 40px) y saltaba entero a una segunda línea — el header
   pasó de 73.75px reales a 130px, sin que `body{padding-top}` ni el
   `scroll-margin-top` de las anclas (#catalogo/#materiales/#contacto) se
   hayan actualizado para ese alto nuevo: de ahí la franja del hero/sección
   anterior asomando debajo del header al hacer clic en esos enlaces.
   Solución: achicar el `column-gap` de esta fila específica (acotado a
   `#masthead`, no tocar `.col-full` en general — esa clase la usa medio
   sitio) lo suficiente para que el carrito vuelva a entrar en la primera
   fila con los 6 ítems. */
#masthead .col-full {
	column-gap: 16px;
}

#masthead .main-navigation ul li a:hover,
#masthead .main-navigation ul li a:focus {
	color: var(--djj-gold);
}

#site-header-cart.site-header-cart a.cart-contents {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	color: var(--djj-cream);
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
}

#site-header-cart .cart-contents .count {
	background: var(--djj-gold);
	color: var(--djj-dark);
	border-radius: 50%;
	padding: 2px 7px;
	font-weight: 600;
	margin-left: 4px;
}

/* Carrito de escritorio: mismo ícono SVG (mask-image) y mismo criterio visual
   que el de móvil (sin texto, badge superpuesto) — bloque NUEVO y separado,
   NO se toca ni la regla general de arriba ni el bloque móvil (@media max-width:767px)
   más abajo, para no arriesgar nada de lo ya ajustado en esa versión. */
@media (min-width: 768px) {
	#site-header-cart.site-header-cart a.cart-contents {
		gap: 0;
		position: relative;
		width: 40px;
		height: 40px;
		justify-content: center;
	}

	/* Storefront dibuja un ícono nativo de Font Awesome (canasta) en ::after —
	   se anula para reemplazarlo por el mismo SVG que en móvil. */
	#site-header-cart .cart-contents::after {
		content: none !important;
	}

	/* Ícono de carrito — reemplaza el carrito con 2 ruedas original por una
	   bolsa/cartera, copiada literal (un solo `path`) del ícono real que se
	   ve en mariohernandez.com.co (sitio de referencia del usuario) —
	   confirmado leyendo el DOM real de ese sitio: el `::after` que arma el
	   ícono visible apunta a un archivo llamado literalmente
	   `icon-shoppingBag...svg`, viewBox `0 0 20 26`, forma SÓLIDA
	   (`fill='black'`, sin `stroke`) — no confundir con el `<symbol
	   id="hpa-cart">` que también existe en el DOM de ese sitio pero está
	   oculto (`display:none`), un remanente sin usar de un carrito con
	   ruedas. El mecanismo `mask-image` funciona igual con una forma
	   sólida: la máscara usa el área rellena en vez de un contorno. */
	#site-header-cart .cart-contents::before {
		content: "";
		display: block;
		/* +21% en total sobre los 22px originales (dos pedidos de +10%
		   consecutivos, el segundo solo en escritorio) — 22 × 1.1 × 1.1 =
		   26.62px. El contador (`.cart-contents .count`, arriba) no se
		   tocó, a pedido explícito del usuario. Móvil se queda en el
		   primer +10% (24.2px, ver el bloque de móvil más abajo). */
		width: 26.62px;
		height: 26.62px;
		background-color: var(--djj-gold);
		/* Calibrado para el ícono anterior (carrito) — a revisar en vivo con
		   esta silueta (proporción distinta, más alta que ancha: 20×26). */
		transform: translateY(-3px);
		-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 26' fill='black'%3E%3Cpath d='M9.46552 25.2C16.9474 24.5623 20.1853 21.6541 19.9918 18.0061L19.45 8.37603V7.73828H14.7803V6.2842C14.7803 2.34287 13.4517 0.200012 10.3557 0.200012C7.01464 0.633686 5.58272 2.63624 5.47952 6.71787L5.46661 7.73828H0.513114L0.022914 16.6413C-0.273782 22.1388 2.28032 25.2 9.46552 25.2ZM10.1493 1.75613C12.1616 1.75613 13.0517 3.12093 13.0517 6.13113V7.73828H7.14365L7.15656 6.32246C6.96306 3.31226 8.08528 1.75613 10.1493 1.75613ZM1.64831 17.5087L2.04812 9.09032L5.44078 9.15409L5.38929 12.0112H7.10491L7.13074 9.1796L13.0646 9.28164V11.9985H14.7803V9.31991L17.8633 9.37093L18.3664 17.3046C18.6115 21.1439 14.4836 23.4781 9.85258 23.5801C4.30565 23.6949 1.49351 20.9653 1.64831 17.5087Z'/%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 20 26' fill='black'%3E%3Cpath d='M9.46552 25.2C16.9474 24.5623 20.1853 21.6541 19.9918 18.0061L19.45 8.37603V7.73828H14.7803V6.2842C14.7803 2.34287 13.4517 0.200012 10.3557 0.200012C7.01464 0.633686 5.58272 2.63624 5.47952 6.71787L5.46661 7.73828H0.513114L0.022914 16.6413C-0.273782 22.1388 2.28032 25.2 9.46552 25.2ZM10.1493 1.75613C12.1616 1.75613 13.0517 3.12093 13.0517 6.13113V7.73828H7.14365L7.15656 6.32246C6.96306 3.31226 8.08528 1.75613 10.1493 1.75613ZM1.64831 17.5087L2.04812 9.09032L5.44078 9.15409L5.38929 12.0112H7.10491L7.13074 9.1796L13.0646 9.28164V11.9985H14.7803V9.31991L17.8633 9.37093L18.3664 17.3046C18.6115 21.1439 14.4836 23.4781 9.85258 23.5801C4.30565 23.6949 1.49351 20.9653 1.64831 17.5087Z'/%3E%3C/svg%3E") center / contain no-repeat;
	}

	/* Oculta visualmente "Carrito", queda solo para lectores de pantalla. */
	#site-header-cart .cart-contents-label {
		position: absolute;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
		border: 0;
	}

	/* ⚠️ Reportado por el usuario con capturas reales — el contador se veía
	   con un dorado distinto según el ancho. Confirmado exhaustivamente que
	   NO es un problema de código: `getComputedStyle` dio el mismo
	   `rgb(201,162,93)` exacto en 6 anchos reales distintos
	   (375/780/820/900/950/1280px), sin ningún estilo en línea ni regla
	   compitiendo, y un refresco forzado (Ctrl+Shift+R/incógnito) del
	   usuario no cambió lo que veía — descarta también caché del
	   navegador. Es un efecto de renderizado (antialiasing de un círculo
	   chico contra el fondo oscuro del header), no algo controlable de
	   forma confiable por CSS. Se probó agrandar el círculo a 20px como
	   mitigación — el usuario reportó que se seguía viendo igual, así que
	   se revirtió a 16px (valores originales `top:-4px; right:-8px`) y se
	   decidió dejar el color como está, sin seguir ajustando. Ver README
	   §7.14 para el detalle completo de la investigación. */
	#site-header-cart .cart-contents .count {
		position: absolute;
		top: -4px;
		right: -8px;
		min-width: 16px;
		height: 16px;
		box-sizing: border-box;
		display: flex;
		align-items: center;
		justify-content: center;
		line-height: 1;
		font-size: 10px;
		padding: 0 3px;
		margin: 0;
	}
}

/* ==================== FOOTER (reskin de Storefront) ====================
   Las 4 columnas (logo+tagline / enlaces / contacto / síguenos) NO son una
   plantilla propia — son las 4 áreas de widgets que Storefront ya trae
   nativas (footer-1..footer-4, storefront_footer_widgets()), pobladas con
   widgets "Custom HTML" nativos de WordPress. Acá solo se reestila el
   markup que Storefront ya genera (.footer-widgets, .footer-widget-N). */
#colophon.site-footer {
	background-color: var(--djj-dark);
	border-top: 1px solid rgba(201, 162, 93, 0.25);
	color: rgba(244, 239, 231, 0.6);
	/* Storefront trae ~26px de padding-top Y ~59px de padding-bottom propios
	   por defecto (mismo patrón que el header, ver 7.5) — sin anularlos, el
	   espacio real no coincide con el que se ajusta en .footer-widgets/
	   .site-info más abajo. El padding-bottom en particular era la causa real
	   del "espacio inferior" grande que reportó el usuario, más que el
	   padding propio de .site-info. */
	padding-top: 0;
	padding-bottom: 0;
}

#colophon a {
	color: var(--djj-gold);
	text-decoration: none;
}

#colophon a:hover {
	text-decoration: underline;
}

#colophon .widget-title {
	color: var(--djj-cream);
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	font-family: 'Poppins', sans-serif;
	margin: 0 0 10px;
}

/* Marca (D&J Joyeros) en su propia fila de ancho completo, arriba de las
   columnas de contenido — pedido explícito del usuario (2026-09-07): antes
   quedaba alineada CON las otras 2 columnas, en la misma fila, en vez de
   como un título de sección propio. Mismo criterio explícito de posición
   por columna/fila que ya usaba el grid (Storefront trae su propio
   float/clear en .block, pensado para su layout original sin grid, que sin
   esto hacía que la 1ª columna no quedara en la fila que le corresponde). */
#colophon .footer-widgets {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 40px;
	/* padding-bottom bajado de 40px a 16px (2026-09-08, pedido explícito del
	   usuario: "reduce el espacio entre los últimos links y el texto de
	   'D&J Joyeros 2026'") — solo afecta escritorio, el
	   `@media(max-width:767px)` de abajo ya lo pone en 0 aparte. */
	padding: clamp(24px, 4vw, 40px) clamp(20px, 5vw, 48px) 16px;
}

/* ⚠️ Bug real, encontrado midiendo en vivo (2026-09-08) al reducir el
   padding de arriba — el espacio real medido (58px) no coincidía con la
   suma de valores explícitos (16px + 10px de `.site-info`). Causa: el
   clearfix heredado de Storefront (`.footer-widgets::after{content:"";
   display:table;}`, pensado para su layout original con floats) se
   convierte en un ITEM DE GRID más — una 3ª fila real, de 0px de alto,
   pero el `gap:40px` de la grilla igual se aplica ANTES de esa fila
   fantasma (confirmado con getComputedStyle: `grid-template-rows` traía
   "...116.5px 0px"), sumando 40px de espacio sin ningún contenido real.
   Sin floats en este layout (todo es grid ahora), el clearfix ya no hace
   falta — se anula el `::before`/`::after` para que la grilla vuelva a
   tener solo 2 filas reales. */
#colophon .footer-widgets::before,
#colophon .footer-widgets::after {
	content: none;
}
#colophon .footer-widget-1 {
	grid-column: 1 / -1;
	grid-row: 1;
	margin-bottom: 8px;
}
#colophon .footer-widget-2 {
	grid-column: 1;
	grid-row: 2;
}
#colophon .footer-widget-3 {
	grid-column: 2;
	grid-row: 2;
}

/* Dentro de la columna de Contacto, Síguenos quedó como una segunda lista
   fusionada en el mismo widget — un poco de separación entre ambas. */
#colophon .djj-footer-list--social {
	margin-top: 16px;
}

#colophon .footer-widgets .block {
	width: auto;
	margin: 0;
	float: none;
}

#colophon .footer-widgets .widget {
	margin: 0;
}

.djj-footer-brand__name {
	font-family: 'Cormorant Garamond', serif;
	font-size: 26px;
	color: var(--djj-cream);
	letter-spacing: 1px;
}

/* Anclas para los ítems de menú "Catálogo" (/#catalogo), "Materiales"
   (/#materiales), "Postventa" (/#posventa) y "Contacto" (/#contacto) — como
   el header es fixed, un salto de ancla común dejaría el título de la
   sección tapado detrás (o, si el valor queda de más, asoma una franja de
   la sección anterior debajo del header); este scroll-margin-top compensa
   exactamente el alto real del header en cada breakpoint.
   ⚠️ Bug real, encontrado al agregar "Postventa" al menú — estos valores
   (91px/116px) habían quedado desactualizados desde que el alto real del
   header se ajustó a 73.24px/73.75px en una sesión anterior (vueltas
   58-61): `body{padding-top}` sí se corrigió entonces, esto no. Con el
   valor viejo (116px en escritorio) de más contra el alto real (73.75px),
   quedaba una franja de ~42px de la sección anterior asomando debajo del
   header al hacer clic — confirmado midiendo en vivo con
   `getBoundingClientRect`, no solo revisando el código. Corregido a los
   mismos valores fraccionarios reales que ya usa `body{padding-top}`
   (7.13), en vez de redondear. */
#catalogo,
#materiales,
#posventa,
#contacto {
	scroll-margin-top: 73.24px;
}

@media (min-width: 768px) {
	#catalogo,
	#materiales,
	#posventa,
	#contacto {
		scroll-margin-top: 73.75px;
	}
}

#colophon .djj-footer-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

#colophon .djj-footer-list li {
	margin-bottom: 12px;
	font-size: 13px;
}

#colophon .djj-footer-list li:last-child {
	margin-bottom: 0;
}

/* Acordeón del footer ("Contacto" / "Privacidad y Términos") — pedido
   explícito del usuario (2026-09-07). El <button> hace doble función: en
   escritorio es solo el título de la columna (sin interacción, mismo look
   que el `.widget-title` que reemplaza — por eso el título vive DENTRO del
   contenido del widget en vez de en el campo "Título" nativo, que ya no se
   usa en estos 2 widgets); en móvil pasa a ser el disparador real del
   desplegable (`.is-open`, ver más abajo y assets/js/cart-drawer.js). Mismo
   mecanismo que ya usa `.djj-filters-toggle` del catálogo (flecha "‹"
   rotada con CSS, sin redibujarla, apaga el flash táctil/outline nativo). */
#colophon .djj-footer-accordion__toggle {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	gap: 6px;
	margin: 0 0 10px;
	padding: 0;
	background: transparent;
	border: none;
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	color: var(--djj-cream);
	text-align: left;
	cursor: default;
}

#colophon .djj-footer-accordion__arrow {
	display: none;
}

/* Escritorio: mismo tratamiento visual que ya usa el panel en móvil al
   desplegarse (blanco, subrayado, con sangría) — pedido explícito del
   usuario (2026-09-08): "como la versión móvil pero sin la opción
   desplegable". En escritorio el panel (<ul>) ya es un bloque siempre
   visible (sin display:none propio fuera del @media de abajo), así que
   solo hace falta el color/subrayado/sangría — nunca se agrega ninguna
   interacción de desplegable acá. */
@media (min-width: 768px) {
	#colophon .djj-footer-accordion__panel {
		padding-left: 16px;
	}

	#colophon .djj-footer-accordion__panel a {
		color: var(--djj-cream);
		text-decoration: underline;
	}
}

@media (max-width: 767px) {
	/* Storefront envuelve .footer-widgets en su propio .col-full, que a este
	   ancho fija un margin lateral fijo en em (~22.65px, mismo patrón ya
	   documentado en la sección "FRONT PAGE" más abajo para el .col-full del
	   contenido) — sin anularlo, las filas del acordeón quedaban ~23px
	   adentro de cada borde en vez de llegar a él. Anulado SOLO dentro de
	   #colophon, no toca el .col-full del resto del sitio. */
	#colophon .col-full {
		margin-left: 0;
		margin-right: 0;
		max-width: none;
	}

	/* Sin padding horizontal acá — las filas del acordeón (línea divisoria +
	   área táctil del botón) tienen que llegar de borde a borde de la
	   pantalla, pedido explícito del usuario (2026-09-07). El padding lateral
	   que antes vivía acá se reparte ahora en cada pieza de contenido por
	   separado (marca / botón-título / lista), ver abajo. Tampoco queda
	   padding-bottom: la última fila (Contacto) se separa de "© D&J Joyeros"
	   solo con su línea divisoria (site-info ya trae su propio border-top),
	   sin aire de más — otro pedido explícito de esta misma vuelta. */
	#colophon .footer-widgets {
		grid-template-columns: 1fr;
		gap: 0;
		padding: 28px 0 0;
	}

	/* Marca ocupa el ancho completo arriba; Contacto y Privacidad y
	   Términos pasan a ser filas apiladas de ancho completo (no columnas
	   lado a lado como en escritorio) — cada una con su propio
	   desplegable. */
	#colophon .footer-widget-1 {
		grid-column: 1;
		grid-row: 1;
		margin-bottom: 20px;
		padding: 0 20px;
	}
	#colophon .footer-widget-2 {
		grid-column: 1;
		grid-row: 2;
	}
	#colophon .footer-widget-3 {
		grid-column: 1;
		grid-row: 3;
	}

	/* La línea (arriba de cada fila) sí va de borde a borde — vive en el
	   contenedor, sin padding lateral propio. El de Contacto no lleva
	   border-bottom propio: el border-top de #colophon .site-info (ya
	   existía, sección 8) hace de línea de cierre, sin duplicar ni dejar
	   hueco entre las dos. */
	#colophon .djj-footer-accordion {
		border-top: 1px solid rgba(201, 162, 93, 0.25);
	}

	/* Alto de la fila cerrada, -20% — pedido explícito del usuario. Medido
	   en vivo antes/después (no calculado a ciegas): el alto real de la
	   fila NO lo marca la línea de texto (17px) sino la caja de línea del
	   ícono, que a 24px de fuente mide ~38.83px de alto natural (el mismo
	   motivo por el que el primer intento de esta vuelta, basado en una
	   medición vieja/cacheada del navegador de pruebas, se quedó corto) —
	   70.83px reales (16px×2 + 38.83px) → 56.67px con este padding. */
	#colophon .djj-footer-accordion__toggle {
		cursor: pointer;
		margin: 0;
		padding: 8.92px 20px;
		outline: none;
		-webkit-tap-highlight-color: transparent;
		-webkit-appearance: none;
		appearance: none;
	}
	#colophon .djj-footer-accordion__toggle:focus,
	#colophon .djj-footer-accordion__toggle:focus-visible,
	#colophon .djj-footer-accordion__toggle:active {
		outline: none;
		background: transparent;
		box-shadow: none;
	}

	/* Ícono +100% (2x) sobre el tamaño anterior (12px, heredado del botón)
	   — pedido explícito del usuario. Tamaño fijo en vez de `em`/`%` para
	   que no dependa de que nadie cambie el font-size del botón después. */
	#colophon .djj-footer-accordion__arrow {
		display: inline-block;
		flex-shrink: 0;
		font-size: 24px;
		color: var(--djj-gold);
		transform: rotate(-90deg);
		transition: transform 0.2s ease;
	}
	#colophon .djj-footer-accordion__toggle.is-open .djj-footer-accordion__arrow {
		transform: rotate(90deg);
	}

	/* Sangría de los ítems al desplegar — pedido explícito del usuario,
	   para que se lean como contenido "adentro" del título, no a la misma
	   profundidad. El padding derecho no cambia (mismo margen que el resto
	   de las filas). */
	#colophon .djj-footer-accordion__panel {
		display: none;
		padding: 0 20px 16px 36px;
	}
	#colophon .djj-footer-accordion__panel.is-open {
		display: block;
	}

	/* Links del desplegable, en blanco y subrayados — pedido explícito del
	   usuario, reemplaza el dorado sin subrayar que usa el resto del
	   footer (#colophon a). Solo dentro del panel, no toca el resto de
	   links del footer. */
	#colophon .djj-footer-accordion__panel a {
		color: var(--djj-cream);
		text-decoration: underline;
	}
}


#colophon .site-info {
	border-top: 1px solid rgba(201, 162, 93, 0.15);
	padding: 10px clamp(20px, 5vw, 48px);
	font-size: 12px;
	text-align: center;
}

/* ==================== FRONT PAGE ==================== */

/* Storefront envuelve #content en un .col-full con max-width ~1064px + padding
   propio — distinto del .col-full del header (#masthead), así que esto NO lo
   afecta. Se anula el límite de ESE .col-full, pero solo en la portada, vía la
   clase "home" que WordPress ya agrega al <body> únicamente en is_front_page()
   — sin tocar el resto de plantillas (catálogo/producto/carrito/checkout).
   (Se probó primero con el truco de vw/calc para "romper" el contenedor desde
   adentro, pero vw incluye el hueco del scrollbar y dejaba un desfase de ~7px;
   apuntar directo al ancestro real es más preciso y no depende del viewport.)
   El fondo de cada sección llega de borde a borde; el ancho de lectura interno
   lo sigue dando el padding propio de cada sección (clamp(20px,5vw,48px) en
   .djj-hero, .djj-catalog, etc.), no este contenedor.

   OJO: Storefront tiene 3 reglas para .col-full (una base + 2 en breakpoints
   angostos) — las de los breakpoints angostos fijan MARGIN (no padding) en em
   fijos (2.617924em / 1.41575em) en vez de "auto". Anular solo max-width y
   padding no alcanza en móvil: ese margin lateral seguía metiendo ~23px de
   cada lado. Hay que anular margin también.
*/
/* Ancho completo también en catálogo, producto individual y "Sobre
   nosotros" — no solo el home. Una sola clase centralizada en <body>
   (djj-full-bleed, agregada por djjoyeros_full_bleed_body_class() en
   functions.php) en vez de listar cada body.xxx acá — para sumar una
   pantalla nueva a "ancho completo" alcanza con agregar su condición en esa
   función de PHP, sin tocar este CSS. El ancho de lectura interno lo sigue
   dando el padding propio de cada sección/contenedor (#primary en catálogo y
   producto, .djj-story en "Sobre nosotros"), no este contenedor — igual que en 9.3. */
body.djj-full-bleed #content > .col-full {
	max-width: none;
	margin-left: 0;
	margin-right: 0;
	padding: 0;
}

/* Storefront trae ~41.9px de margin-bottom propio en <main id="primary">
   (misma escala de espaciado que ya causó el bug del header/footer, 7.5/8) —
   como ninguna sección propia cubre ese margen con su color de fondo, se
   veía como una franja en blanco entre el final del contenido (ej. la
   sección de Instagram del home) y el footer. */
body.djj-full-bleed #primary {
	margin-bottom: 0;
}

.djj-front {
	background: var(--djj-dark);
}

.djj-diamond {
	width: 6px;
	height: 6px;
	background: var(--djj-gold);
	transform: rotate(45deg);
	flex-shrink: 0;
	display: inline-block;
}

/* Hero — fondo fotográfico rotativo (2 fotos reales de producto, ver
   comentario en front-page.php) detrás del texto fijo, en vez del panel
   dividido texto/foto original. Estructura de capas (todas absolutas
   dentro de `.djj-hero`, position:relative):
     .djj-hero__bg (z-index 0)   → las 2 fotos en cross-fade
     .djj-hero::before (z-index 1) → scrim oscuro + resplandor dorado ya
                                      usado en el sitio, para legibilidad
                                      del texto sobre cualquiera de las 2 fotos
     .djj-hero__sweep (z-index 2)  → destello de luz único al cargar
     .djj-hero__copy (z-index 3)   → texto + botón, esquina inferior
                                      izquierda (ver esa regla más abajo)

   Alto ya NO es un pixelaje fijo (antes `min-height:560px`, igual sin
   importar el ancho — reportado por el usuario), sino `aspect-ratio`: la
   sección escala su alto en proporción al ancho, siempre 100% del ancho
   real disponible. Escritorio en `12/5` (antes `11/5`, 2026-08-31,
   pedido explícito) — no coincide exacto con el recorte del archivo
   fuente (1859×845px = 11:5), así que `object-fit:cover` sí recorta
   parte de la imagen, con sesgo hacia arriba a pedido del usuario
   (`object-position` en el `@media (min-width:768px)` de
   `.djj-hero__bg-frame img`, más abajo). Móvil en `3/4` (ver @media más
   abajo) — el archivo fuente móvil se re-recortó a 634×845px para
   calzar con ese mismo `3/4` (ver comentario junto al @media: alto
   completo de la imagen, solo se recorta el ancho), así que acá
   `object-fit:cover` (misma regla base que escritorio, sin override)
   no pierde nada perceptible de la foto. */
.djj-hero {
	position: relative;
	display: flex;
	align-items: center;
	aspect-ratio: 12 / 5;
	background: linear-gradient(135deg, var(--djj-dark) 0%, var(--djj-teal) 100%);
	padding: 80px clamp(20px, 5vw, 48px);
	overflow: hidden;
}

.djj-hero__bg {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.djj-hero__bg-frame {
	position: absolute;
	inset: 0;
	opacity: 0;
	animation: djj-hero-crossfade 11s ease-in-out infinite;
}

.djj-hero__bg-frame--1 {
	animation-delay: 0s;
}

.djj-hero__bg-frame--2 {
	animation-delay: 5.5s;
}

.djj-hero__bg-frame picture {
	display: block;
	width: 100%;
	height: 100%;
}

.djj-hero__bg-frame img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Escritorio: sesga el recorte de `object-fit:cover` hacia abajo
   (Y > 50%), perdiendo más franja de arriba que de abajo de la imagen
   — pedido explícito del usuario al pasar `.djj-hero` a `aspect-ratio:
   12/5` (arriba), que ya no coincide exacto con el 11:5 del archivo
   fuente. Sin este ajuste el recorte por defecto es centrado (mitad
   arriba, mitad abajo). 70% ajustado a ojo comparando varios valores en
   vivo (50/60/65/70/75/85/100) — a partir de 85% el logo "D&J JOYEROS"
   de la caja ya queda muy pegado al borde superior; 70% deja ese margen
   cómodo y el jarrón de flores completo, con un sesgo hacia abajo claro. */
@media (min-width: 768px) {
	.djj-hero__bg-frame img {
		object-position: 50% 70%;
	}
}

/* 2 tramos por imagen, sobre un ciclo de 11s (50% = 5.5s c/u) — mismo
   ritmo de fundido que antes (~0.66s de entrada/salida, ahora 6% de 11s
   en vez de 4% de 16.5s), solo que con 2 fotos en vez de 3: entra
   (0-6%), se sostiene (6-44%), sale (44-50%), invisible el resto del
   ciclo hasta que le toca de nuevo. */
@keyframes djj-hero-crossfade {
	0% { opacity: 0; }
	6% { opacity: 1; }
	44% { opacity: 1; }
	50% { opacity: 0; }
	100% { opacity: 0; }
}

.djj-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background-image:
		linear-gradient(135deg, rgba(10, 26, 34, 0.62) 0%, rgba(14, 58, 67, 0.4) 100%),
		radial-gradient(circle at 20% 25%, rgba(201, 162, 93, 0.18), transparent 45%);
	pointer-events: none;
}

/* Destello de luz una sola vez al cargar — barre la primera imagen con un
   trazo dorado diagonal. `animation-iteration-count:1` + `forwards`, no
   hay loop. */
.djj-hero__sweep {
	position: absolute;
	inset: 0;
	z-index: 2;
	background-image: linear-gradient(115deg, transparent 42%, rgba(201, 162, 93, 0.55) 50%, transparent 58%);
	background-size: 260% 100%;
	background-position: 160% 0;
	animation: djj-hero-sweep 1.2s ease-out 0.4s 1 forwards;
	pointer-events: none;
}

@keyframes djj-hero-sweep {
	from { background-position: 160% 0; }
	to { background-position: -60% 0; }
}

/* Bajo prefers-reduced-motion: sin cross-fade (queda fija la primera
   imagen) y sin destello — sin romper el layout, solo se anulan las
   animaciones. */
@media (prefers-reduced-motion: reduce) {
	.djj-hero__bg-frame {
		animation: none;
		opacity: 0;
	}

	.djj-hero__bg-frame--1 {
		opacity: 1;
	}

	.djj-hero__sweep {
		animation: none;
		opacity: 0;
	}
}

/* Texto + CTA juntos, en la esquina inferior izquierda de `.djj-hero`
   (2026-08-31, pedido explícito: "baja el texto que quede justo encima
   del botón"). Antes el texto vivía centrado por el `align-items:center`
   del padre y el botón se sacaba como hermano aparte para poder
   posicionarse solo — ya no hace falta separarlos: sin el párrafo que
   había antes (se quitó, pedido explícito), el único contenido restante
   es el título y el botón, así que ahora viven juntos dentro de este
   mismo contenedor, que es el que se posiciona en absoluto contra
   `.djj-hero`. */
.djj-hero__copy {
	position: absolute;
	z-index: 3;
	left: clamp(20px, 5vw, 48px);
	bottom: clamp(20px, 5vw, 48px);
	max-width: 540px;
}

.djj-hero__copy h1 {
	font-family: 'Cormorant Garamond', serif;
	font-style: italic;
	font-weight: 400;
	font-size: clamp(38px, 5vw, 60px);
	line-height: 1.08;
	color: var(--djj-cream);
	margin: 0 0 16px;
}

.djj-btn {
	display: inline-block;
	padding: 16px 32px;
	background: var(--djj-gold);
	color: var(--djj-dark);
	font-size: 12px;
	letter-spacing: 1.5px;
	font-weight: 600;
	text-transform: uppercase;
	border: none;
	cursor: pointer;
	font-family: 'Poppins', sans-serif;
	text-decoration: none;
}

/* CTA del Hero — antes botón sólido (`.djj-btn`, fondo dorado) con el
   texto "Ver colección"; ahora texto subrayado con el mismo destino
   (`#catalogo`) y el texto "Ver catálogo" (2026-08-31, pedido explícito:
   "cambia el botón por texto subrayado que tenga la misma
   funcionalidad"). Vive en el flujo normal dentro de `.djj-hero__copy`
   (ya no `position:absolute` aparte, ver esa regla arriba) — el
   `margin-top` lo separa del título por encima. */
.djj-hero__cta {
	display: inline-block;
	margin-top: 4px;
	color: var(--djj-cream);
	font-family: 'Jost', sans-serif;
	font-size: 13px;
	letter-spacing: 1px;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 4px;
}

/* ⚠️ Bug real, reportado por el usuario — "Ver catálogo" quedaba dorado
   después de tocarlo en móvil, como si quedara "seleccionado". No era un
   problema de foco (`outline`) — es el efecto nativo de los navegadores
   táctiles de aplicar `:hover` en el toque y no quitarlo hasta tocar otra
   cosa (no hay mouse real que "salga" del elemento). `@media (hover:hover)`
   hace que esta regla SOLO aplique en dispositivos con mouse de verdad
   (`hover:none` en táctiles) — en escritorio no cambia nada. */
@media (hover: hover) {
	.djj-hero__cta:hover {
		color: var(--djj-gold);
	}
}

.djj-btn:hover {
	background: var(--djj-cream);
	color: var(--djj-dark);
}

.djj-btn-outline {
	display: inline-block;
	padding: 15px 32px;
	border: 1px solid var(--djj-gold);
	background: var(--djj-gold);
	color: var(--djj-dark);
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	text-decoration: none;
}

.djj-btn-outline:hover {
	background: var(--djj-cream);
	border-color: var(--djj-cream);
	color: var(--djj-dark);
}

/* Encabezados de sección */
.djj-heading {
	text-align: center;
	margin-bottom: 56px;
}

.djj-heading__eyebrow {
	font-size: 13px;
	letter-spacing: 3px;
	color: var(--djj-gold);
	text-transform: uppercase;
}

.djj-heading h2 {
	font-size: 38px;
	margin: 14px 0 0;
}

.djj-heading p {
	font-size: 15px;
	margin: 14px auto 0;
	max-width: 480px;
}

.djj-heading--dark h2 {
	color: var(--djj-cream);
}

.djj-heading--light h2 {
	color: var(--djj-dark);
}

.djj-heading--light p {
	color: var(--djj-teal);
	opacity: 0.75;
}

/* Nueva colección */
/* Catálogo */
.djj-catalog {
	/* Borde lateral fijo a 15px en escritorio (antes clamp(20px,5vw,48px),
	   a pedido explícito del usuario, 2026-08-31). En móvil sigue mandando
	   el override propio de @media max-width:767px (5px, vuelta 153), sin
	   relación con este valor.

	   padding-top a la mitad del original (2026-08-31, pedido explícito:
	   "espacio muy grande entre el header [Hero] y el texto catálogo") —
	   antes compartía el mismo `clamp(56px,10vw,120px)` que el padding
	   inferior (120px reales medidos a 1280px, el hueco real reportado).
	   Ahora es la mitad exacta de cada extremo del clamp: `clamp(28px,5vw,60px)`.

	   padding-bottom unificado al mismo valor (2026-08-31, mismo criterio
	   "estándar" aplicado a las 4 secciones del home — Catálogo/Materiales/
	   Posventa/Instagram comparten esta misma fórmula de ahora en más). */
	padding-top: clamp(28px, 5vw, 60px);
	padding-bottom: clamp(28px, 5vw, 60px);
	padding-left: 15px;
	padding-right: 15px;
	background: var(--djj-cream);
}

.djj-catalog__grid {
	display: grid;
	/* Máximo 5 tarjetas por fila en escritorio (2026-08-31, pedido
	   explícito) — con `auto-fit` simple, una pantalla lo bastante ancha
	   podía llegar a mostrar las 7 categorías en una sola fila. El truco
	   de `max()` fuerza el ancho mínimo de columna a subir junto con el
	   contenedor: `(100% - 4 gaps) / 5` es el ancho exacto de columna
	   cuando hay 5 por fila, así que una 6ª columna nunca llega a caber
	   (el propio `auto-fit` la manda a la fila siguiente). En pantallas
	   angostas ese cálculo da menos de 240px y gana el `240px` fijo —
	   ahí sigue mandando el mínimo de siempre, con menos de 5 por fila. */
	grid-template-columns: repeat(auto-fit, minmax(max(240px, (100% - 4 * 15px) / 5), 1fr));
	/* 15px en escritorio (antes 32px, mismo pedido) — en móvil sigue
	   mandando el override propio (5px, vuelta 154). */
	gap: 15px;
}

.djj-catalog__card {
	position: relative;
	display: flex;
	flex-direction: column;
	background: #FFFFFF;
	border: 1px solid rgba(14, 58, 67, 0.12);
	text-decoration: none;
	color: inherit;
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.djj-catalog__card:hover {
	border-color: var(--djj-gold);
	box-shadow: 0 4px 16px rgba(10, 26, 34, 0.12);
}

/* Cuadradas en cualquier ancho (2026-08-31, pedido explícito del usuario:
   "en escritorio se ven cuadradas pero en móvil no") — antes era
   `height:260px` fijo en escritorio y `height:160px` fijo en móvil
   (@media max-width:767px, ver abajo), cuadrado solo por coincidencia en
   escritorio (a 1280px el ancho real de columna daba ~268px, cerca de
   260px) y claramente no cuadrado en móvil (~180px de ancho de columna
   contra 160px de alto). `aspect-ratio:1/1` da cuadrado real, siempre,
   sin depender del ancho real de columna en cada breakpoint — mismo
   mecanismo que ya usan la grilla del catálogo de productos (10.7) y la
   galería de la ficha de producto. */
.djj-catalog__image {
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	display: block;
}

.djj-catalog__image--placeholder {
	aspect-ratio: 1 / 1;
	display: flex;
	align-items: center;
	justify-content: center;
	background: linear-gradient(135deg, var(--djj-teal), var(--djj-dark));
	color: rgba(244, 239, 231, 0.5);
	font-size: 13px;
	letter-spacing: 1px;
	text-align: center;
	padding: 20px;
	box-sizing: border-box;
}

/* Nombre de la categoría, movido de debajo de la foto a superpuesto sobre
   su borde inferior (2026-08-31, pedido explícito del usuario) — antes
   era un bloque propio con fondo crema debajo de la imagen. `position:absolute`
   contra `.djj-catalog__card` (ya `position:relative`); el degradado oscuro
   de abajo hacia arriba asegura que el texto blanco se lea sobre cualquier
   foto, clara u oscura, sin depender del contenido real de cada categoría. */
.djj-catalog__body {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 16px 12px;
	text-align: center;
	background: linear-gradient(to top, rgba(10, 26, 34, 0.72) 0%, rgba(10, 26, 34, 0.32) 65%, transparent 100%);
}

.djj-catalog__name {
	font-size: 25.2px; /* +20% (2026-08-31, pedido explícito), antes 21px */
	color: var(--djj-cream);
	font-family: 'Cormorant Garamond', serif;
	/* Sombreado negro alrededor de la letra (2026-08-31, pedido explícito,
	   aumentado el mismo día tras el primer ajuste) — refuerzo extra de
	   legibilidad además del degradado de `.djj-catalog__body`, sobre todo
	   contra fotos claras donde el degradado pesa menos cerca del borde
	   inferior. 2 capas: un halo simétrico (sin offset, `0 0`) para que se
	   note "alrededor" de la letra y no solo hacia abajo, más la sombra
	   original con más blur y opacidad que el primer intento (antes
	   `0 1px 3px / 0.45`). */
	text-shadow: 0 0 4px rgba(0, 0, 0, 0.6), 0 1px 4px rgba(0, 0, 0, 0.55);
	/* Bajado 5px (2026-08-31, pedido explícito) — solo el texto, no todo
	   `.djj-catalog__body` (que definiría el área del degradado), para no
	   cambiar el alcance del scrim. */
	transform: translateY(5px);
}

/* Catálogo por Sexo (10.24) — entre Catálogo por categoría y Materiales.
   2 imágenes (ya traen el texto integrado, "Catálogo/Joyas para Mujeres"/
   "...Hombres") que enlazan directo a los archivos nativos de WooCommerce
   del atributo pa_sexo (/sexo/mujer/, /sexo/hombre/). Mismo "estándar" de
   separación vertical que el resto de las secciones del home
   (clamp(28px,5vw,60px), ver comentario en .djj-catalog). */
.djj-gender-catalog {
	padding-top: clamp(28px, 5vw, 60px);
	padding-bottom: clamp(28px, 5vw, 60px);
	padding-left: 15px;
	padding-right: 15px;
	background: var(--djj-cream);
}

/* Escritorio: una al lado de la otra, 35px de separación — pedido explícito
   del usuario. `1fr 1fr` en vez de `auto-fit` (a diferencia de
   .djj-catalog__grid): acá siempre son exactamente 2 imágenes, sin
   necesitar que la grilla decida cuántas caben por fila. */
.djj-gender-catalog__grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 35px;
}

/* Envuelve la tarjeta (imagen) y su vista previa de productos (10.24e+)
   como una sola unidad dentro de la grilla (2026-09-04, agregado para
   poder fijar el espacio ENTRE ambas en 5px sin afectar el `gap:35px` de
   arriba, que sigue siendo el espacio entre Mujer y Hombre). Sin este
   envoltorio, los 2 elementos (tarjeta y vista previa) eran hijos directos
   de la grilla y compartían el mismo `gap` — no había forma de que el
   espacio "tarjeta→vista previa" fuera distinto del espacio "vista
   previa→siguiente tarjeta" usando un solo valor de `gap`. */
.djj-gender-catalog__group {
	display: block;
	/* ⚠️ Bug real, encontrado verificando en vivo (10.24i) — sin esto, el
	   carrusel de 6 productos (`.djj-gender-catalog__preview-track`, ver
	   abajo) inflaba la columna `1fr` de la grilla de escritorio/el `100vw`
	   de móvil hasta caber TODO el contenido sin recortar (494px medidos en
	   una pantalla de 375px), aunque el track tenga `overflow-x:hidden` —
	   ese `overflow` solo recorta lo que se PINTA, no cambia el tamaño
	   mínimo ("min-content") que CSS Grid/Flexbox le reservan al elemento
	   por default (`min-width:auto`). `min-width:0` en este contenedor
	   (grid item real de `.djj-gender-catalog__grid`) corta esa cadena de
	   herencia de tamaño mínimo antes de que llegue a la grilla. */
	min-width: 0;
}

.djj-gender-catalog__card {
	display: block;
	line-height: 0; /* sin esto, el <img> inline deja ~4-5px de espacio fantasma debajo (line-height del contenedor) */
	transition: opacity 0.2s ease;
}

.djj-gender-catalog__card:hover {
	opacity: 0.92;
}

/* Eyebrow "Catálogo Mujer"/"Catálogo Hombre" por tarjeta, encima de cada
   imagen (2026-09-04, pedido explícito) — mismo estilo que `.djj-heading__eyebrow`
   (dorado, mayúsculas, 13px, 3px de tracking), pero repetido POR TARJETA en
   vez de una sola vez por sección, ya que acá hay 2 imágenes en vez de un
   único <h2>. `display:block` + `line-height:normal` propio: el padre
   `.djj-gender-catalog__card` usa `line-height:0` (ver comentario arriba,
   evita espacio fantasma bajo el <img>), que heredaría acá y colapsaría
   la línea de texto a 0px si no se resetea explícitamente. */
.djj-gender-catalog__eyebrow {
	display: block;
	line-height: normal;
	font-size: 13px;
	letter-spacing: 3px;
	color: var(--djj-gold);
	text-transform: uppercase;
	text-align: center;
	margin-bottom: 14px;
}

.djj-gender-catalog__image-wrap {
	position: relative;
	display: block;
}

.djj-gender-catalog__image {
	display: block;
	width: 100%;
	height: auto;
}

/* Botón "Ver colección" — pedido explícito del usuario (2026-09-09):
   encima de la foto (no debajo, como un elemento aparte), pegado a su
   borde inferior, centrado respecto al ancho de la foto. Reusa el mismo
   componente visual que ya usa el resto del sitio (`.djj-btn-outline`,
   fondo dorado sólido) en vez de un link de solo texto — sobre una foto
   real, un fondo sólido resuelve la legibilidad sin depender de a qué
   tan clara/oscura salga la zona inferior de cada imagen. Vive DENTRO
   del mismo `<a>` de la tarjeta (no es un link propio) — un `<a>` anidado
   dentro de otro `<a>` no es HTML válido. */
.djj-gender-catalog__cta {
	position: absolute;
	left: 50%;
	bottom: 20px;
	transform: translateX(-50%);
	white-space: nowrap;
}

/* Vista previa de productos reales debajo de cada tarjeta — SOLO en
   móvil, a pedido explícito del usuario (10.24e). Oculta por defecto
   (`display:none`, no el `display:flex` real de móvil): ahora vive
   DENTRO de `.djj-gender-catalog__group` (ver arriba), ya no es hijo
   directo de la grilla de escritorio — pero se deja igual en `display:
   none` acá (belt-and-suspenders) para no depender de que el `@media`
   de abajo sea siempre la única fuente de verdad. */
.djj-gender-catalog__preview {
	display: none;
}

.djj-gender-catalog__preview-item {
	display: block;
	text-decoration: none;
	color: inherit;
}

/* Imagen del producto, agregada encima de nombre/precio (10.24f, pedido
   posterior del usuario) — mismo `aspect-ratio:1/1` + `object-fit:cover`
   que ya usan las tarjetas reales del catálogo por categoría
   (`.woocommerce ul.products li.product img`), para que la vista previa
   se vea igual de "cuadrada" que el resto del sitio. `get_image()` ya
   imprime su propio `<img>` (con placeholder incluido si el producto no
   tiene foto) — este `<span>` solo controla el tamaño/recorte del
   contenedor, sin pisar los atributos que trae ese `<img>`. */
.djj-gender-catalog__preview-image {
	display: block;
	margin-bottom: 8px;
}

.djj-gender-catalog__preview-image img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	height: auto;
	object-fit: cover;
}

.djj-gender-catalog__preview-name {
	display: block;
	font-family: 'Cormorant Garamond', serif;
	font-size: 17px;
	line-height: 1.3;
	color: var(--djj-teal);
}

/* Mismo criterio de tipografía/color que el precio de las tarjetas del
   catálogo por categoría (`.woocommerce ul.products li.product .price`),
   para que la vista previa no introduzca un estilo de precio nuevo. */
.djj-gender-catalog__preview-price {
	display: block;
	margin-top: 2px;
	font-family: 'Poppins', sans-serif;
	font-size: 14px;
	font-weight: 700;
	color: var(--djj-dark);
}

/* Flechas "<"/">" (10.24i/j, pedido explícito del usuario: "serán botones
   para pasar entre productos", en bucle infinito — nunca desaparecen, ver
   catalog-filters.js) — se imprimen solo cuando hay más de 2 productos
   cargados (`djjoyeros_render_gender_catalog_preview()`, 10 por defecto),
   para no ofrecer un botón que no tenga a dónde ir. Ancho fijo IGUAL al
   padding lateral de `.djj-gender-catalog__preview` (40px, ver `@media`
   abajo) — no una posición en px a mano — así el símbolo queda centrado en
   esa franja exacta pase lo que pase con el tamaño de fuente, vía
   `text-align:center` en vez de calcular el ancho real del glifo.

   `top:50%` acá es solo un respaldo antes de que `catalog-filters.js`
   corra (10.24j, pedido explícito: "a la mitad de la ALTURA DE LAS
   IMÁGENES", no del bloque completo con nombre/precio abajo) — ese script
   mide la altura real de la imagen (cambia según el ancho de pantalla, al
   ser cuadrada) y sobrescribe `top` con un valor en px exacto, en
   `window.load`/`resize`. El clic en sí (mover el scroll del carrusel)
   también lo maneja `catalog-filters.js`. */
.djj-gender-catalog__preview-arrow {
	display: none;
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 40px;
	text-align: center;
	background: none;
	border: none;
	padding: 0;
	margin: 0;
	font-family: 'Poppins', sans-serif;
	/* +10% (pedido explícito) — antes 22px. */
	font-size: 24.2px;
	font-weight: 700;
	line-height: 1;
	/* Azul petróleo de la paleta (10.24j, pedido explícito) — antes dorado. */
	color: var(--djj-teal);
	cursor: pointer;
	/* ⚠️ El usuario confirmó, probando en su propio celular, que seguía
	   quedando un resaltado gris tras el toque — `outline:none` +
	   `-webkit-tap-highlight-color:transparent` (intento anterior) no
	   alcanzaron solos. Se suma `-webkit-appearance:none`/`appearance:none`
	   (saca el `<button>` del "chrome" nativo del sistema operativo, que en
	   algunas versiones de Android incluye su propio indicador de foco/
	   presionado por fuera de `outline`) y `:focus-visible` explícito,
	   además de `:focus`/`:active` — cubriendo los 3 estados por separado
	   en vez de asumir que uno solo alcanza. */
	outline: none;
	-webkit-tap-highlight-color: transparent;
	-webkit-appearance: none;
	appearance: none;
}

.djj-gender-catalog__preview-arrow:focus,
.djj-gender-catalog__preview-arrow:focus-visible,
.djj-gender-catalog__preview-arrow:active {
	outline: none;
	background: none;
	box-shadow: none;
}

.djj-gender-catalog__preview-arrow--prev {
	left: 0;
}

.djj-gender-catalog__preview-arrow--next {
	right: 0;
}

@media (max-width: 767px) {
	/* Ancho de pantalla real (sangrado, sin el padding lateral de la
	   sección) — pedido explícito del usuario. Mismo mecanismo exacto que
	   ya usa `.djj-materials__grid` en móvil (100vw + margen negativo) en
	   vez de solo `padding:0`, para no depender de que ningún ancestro le
	   deje el 100% real del viewport disponible. */
	.djj-gender-catalog {
		padding-left: 0;
		padding-right: 0;
	}

	.djj-gender-catalog__grid {
		grid-template-columns: 1fr;
		gap: 35px;
		width: 100vw;
		margin-left: calc(50% - 50vw);
		margin-right: calc(50% - 50vw);
	}

	/* La tarjeta/imagen sí queda a sangre completa (100vw, ver arriba) —
	   la vista previa necesita su propio padding lateral de vuelta, para
	   que el nombre/precio no queden pegados al borde de la pantalla.
	   40px a cada lado — pedido explícito del usuario (2026-09-04, mismo
	   valor que el ancho de `.djj-gender-catalog__preview-arrow` arriba,
	   para que la flecha quede DENTRO de esa franja, no fuera de ella).
	   `position:relative` para anclar las flechas (`position:absolute`)
	   contra este mismo contenedor. `margin-top:10px` (5px, 10.24i, + 5px
	   más, pedido explícito posterior) — espacio real entre la imagen
	   principal (tarjeta) y esta fila, distinto del `gap:35px` de la
	   grilla (ver comentario en `.djj-gender-catalog__group` más arriba). */
	.djj-gender-catalog__preview {
		display: flex;
		align-items: center;
		position: relative;
		margin-top: 10px;
		padding: 0 40px;
		/* Mismo motivo que `.djj-gender-catalog__group` arriba — cortar la
		   cadena de `min-width:auto` en cada nivel (grid → aquí → track),
		   no solo en el primero, para que ninguno de los 2 vuelva a heredar
		   el ancho mínimo real del contenido de 6 productos. */
		min-width: 0;
	}

	.djj-gender-catalog__preview-arrow {
		display: block;
	}

	/* El carrusel real: recorta a exactamente 2 productos visibles
	   (`overflow-x:hidden` + cada item a mitad del ancho disponible) y se
	   desplaza vía `scrollLeft` desde `catalog-filters.js` al hacer clic en
	   una flecha — `scroll-snap` alinea siempre al borde del producto
	   siguiente/anterior, sin quedar "a mitad" de uno. 10px entre
	   productos — pedido explícito del usuario (2026-09-04); cada item
	   resta la mitad de ese gap (`calc(50% - 5px)`) para que sigan siendo
	   exactamente 2 por fila con el gap real en el medio. */
	.djj-gender-catalog__preview-track {
		display: flex;
		gap: 10px;
		flex: 1 1 auto;
		min-width: 0;
		/* ⚠️ Bug real, encontrado verificando el clic real de las flechas
		   (10.24i) — `overflow-x:hidden` no solo recorta lo que se pinta,
		   también le quita al elemento su propio "scroll container": ni
		   `scrollLeft = X` por JS ni el usuario arrastrando con el dedo
		   pueden moverlo (confirmado en vivo: `track.scrollLeft = 100` no
		   cambiaba nada con `hidden`). `auto` lo deja scrolleable de
		   verdad; la barra de scroll nativa se oculta aparte, abajo, para
		   que seguir viéndose igual que antes. */
		overflow-x: auto;
		-ms-overflow-style: none;
		scrollbar-width: none;
		/* `auto`, no `smooth` — la animación la hace `catalog-filters.js` a
		   mano con `requestAnimationFrame` (ver ese comentario: ni el
		   `scroll-behavior` nativo ni `scrollTo({behavior})` funcionaban de
		   forma confiable en el navegador real donde se probó). Con
		   `smooth` acá, cada uno de los frames que escribe esa animación
		   dispararía SU PROPIA animación nativa superpuesta — se deja en
		   `auto` para que cada asignación de `scrollLeft` sea instantánea y
		   el único movimiento visible sea el de la animación propia. */
		scroll-behavior: auto;
		scroll-snap-type: x mandatory;
	}

	.djj-gender-catalog__preview-track::-webkit-scrollbar {
		display: none;
	}

	.djj-gender-catalog__preview-item {
		flex: 0 0 calc(50% - 5px);
		scroll-snap-align: start;
	}
}

/* Materiales — de swatch circular + texto aparte a una foto por material con
   el nombre/tagline ya integrados en la imagen. Escritorio: panel de foto
   pegado al borde derecho de la sección (arriba/abajo tocan los bordes
   reales de la sección, ancho derivado del alto vía `aspect-ratio` — nunca
   se recorta), texto a la derecha en el espacio que queda libre. Rota con
   cross-fade (una foto a la vez). Ver el `@media (max-width:767px)` más
   abajo para los ajustes de móvil (foto a ancho completo + puntos
   indicadores). */
.djj-materials {
	--djj-materials-img-h: clamp(420px, 40vw, 640px);
	position: relative;
	overflow: hidden;
	min-height: var(--djj-materials-img-h);
	padding: clamp(48px, 9vw, 100px) clamp(20px, 5vw, 48px);
	/* dejar libre, a la derecha, el ancho real de la foto (alto × 1.5) + el
	   padding normal de la sección. */
	padding-right: calc(var(--djj-materials-img-h) * 1.5 + clamp(20px, 5vw, 48px));
	background: var(--djj-cream);
}

/* El texto ya no se pega al borde de la imagen (text-align:right) — al ser
   un bloque normal, ya ocupa exactamente el espacio entre el padding
   izquierdo de la sección y el borde izquierdo de la imagen (gracias al
   `padding-right` de arriba); con `center` queda centrado dentro de esa
   franja completa, no pegado a ninguno de los dos extremos. */
.djj-materials .djj-heading {
	text-align: center;
}

/* El alto ya no es un porcentaje del contenedor — es el mismo valor que
   `.djj-materials` usa como `min-height`, así que el panel y la sección
   siempre miden exactamente lo mismo (`top:0`, sin `bottom`/`transform`:
   ambos bordes coinciden con los de la sección por construcción). */
.djj-materials__grid {
	position: absolute;
	top: 0;
	right: 0;
	height: var(--djj-materials-img-h);
	width: auto;
	aspect-ratio: 765 / 510;
}

.djj-materials__card {
	position: absolute;
	inset: 0;
	opacity: 0;
	animation: djj-materials-crossfade 22s ease-in-out infinite;
}

.djj-materials__card:nth-child(1) { animation-delay: 0s; }
.djj-materials__card:nth-child(2) { animation-delay: 5.5s; }
.djj-materials__card:nth-child(3) { animation-delay: 11s; }
.djj-materials__card:nth-child(4) { animation-delay: 16.5s; }

.djj-materials__photo {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Puntos indicadores — solo se muestran en móvil (ver media query), pero
   la regla base los oculta para que no aparezcan de más en escritorio. */
.djj-materials__dots {
	display: none;
}

/* 4 tramos (entra/sostiene/sale/invisible), repartidos en 4 fotos sobre un
   ciclo de 22s (5.5s c/u). */
@keyframes djj-materials-crossfade {
	0% { opacity: 0; }
	3% { opacity: 1; }
	22% { opacity: 1; }
	25% { opacity: 0; }
	100% { opacity: 0; }
}

/* Mismo reparto de tiempos que arriba, pero animando el color de fondo del
   punto en vez de la opacidad de la foto — sin JS, sincronizado solo por
   compartir el mismo `animation-delay` que su foto correspondiente. */
@keyframes djj-materials-dot {
	0% { background-color: transparent; }
	3% { background-color: var(--djj-gold); }
	22% { background-color: var(--djj-gold); }
	25% { background-color: transparent; }
	100% { background-color: transparent; }
}

@media (prefers-reduced-motion: reduce) {
	.djj-materials__card {
		animation: none;
		opacity: 0;
	}

	.djj-materials__card:nth-child(1) {
		opacity: 1;
	}

	.djj-materials__dot {
		animation: none;
		background-color: transparent;
	}

	.djj-materials__dot--1 {
		background-color: var(--djj-gold);
	}
}

/* Modo manual — activado por JS (assets/js/cart-drawer.js,
   djjBindMaterialsSwipe()) en cuanto el usuario desliza el dedo sobre la
   foto de Materiales, pedido explícito (2026-09-08, solo móvil: "permite
   cambiar la imagen de materiales desplazando con el dedo"). Apaga en
   seco la animación automática de las 4 fotos/puntos — a partir de acá el
   control es 100% de la clase `.is-active` que mueve el JS, sin volver a
   auto-rotar. */
.djj-materials--manual .djj-materials__card {
	animation: none;
	opacity: 0;
}

.djj-materials--manual .djj-materials__card.is-active {
	opacity: 1;
}

.djj-materials--manual .djj-materials__dot {
	animation: none;
	background-color: transparent;
}

.djj-materials--manual .djj-materials__dot.is-active {
	background-color: var(--djj-gold);
}

/* Escritorio: mismo patrón "todo centrado y apilado" que ya usa móvil
   (texto arriba, una sola foto rotativa contenida y centrada abajo, con
   puntos indicadores) — reemplaza el panel pegado al borde derecho de
   arriba (2026-08-31, pedido explícito del usuario, con una captura de
   referencia del layout deseado). La foto ya no se estira a la altura
   completa de la sección ni se pega al borde — queda contenida, centrada,
   con una sombra suave en vez de sangrar hasta el borde.

   Llevado a producción primero SOLO en su versión de layout puro (vuelta
   169) — el párrafo descriptivo se sumó después (vuelta 181), con texto
   final ya definido; el bloque "También trabajamos" que había existido
   en pruebas se eliminó por completo antes de llegar a aprobarse, nunca
   existió en producción. */
@media (min-width: 768px) {
	.djj-materials {
		/* Ya no hace falta reservar alto fijo ni el hueco a la derecha del
		   panel — la foto ahora es un bloque normal, centrado, que aporta
		   su propio alto. */
		min-height: 0;
		/* Padding vertical "estándar" del home (mismo valor que
		   `.djj-catalog`/`.djj-services`/`.djj-instagram`, ver esas
		   reglas) — antes heredaba clamp(48px,9vw,100px) de la base. */
		padding-top: clamp(28px, 5vw, 60px);
		padding-right: clamp(20px, 5vw, 48px);
		padding-bottom: clamp(28px, 5vw, 60px);
		/* La sombra de `.djj-materials__grid` de abajo necesita espacio
		   para no recortarse contra el `overflow:hidden` de la regla base
		   (pensado para el panel absoluto que ya no existe acá). */
		overflow: visible;
	}

	/* Ancho máximo más generoso que el genérico de `.djj-heading p`
	   (480px) — a pedido explícito del usuario, para que el párrafo no
	   quede angosto contra el resto de la sección. Solo acá, no toca la
	   regla genérica que comparten Catálogo/Posventa. */
	.djj-materials .djj-heading p {
		max-width: 640px;
	}

	.djj-materials__grid {
		position: relative;
		top: auto;
		right: auto;
		height: auto;
		width: min(600px, 90%);
		margin: 0 auto;
		box-shadow: 0 20px 48px rgba(10, 26, 34, 0.18);
	}

	.djj-materials__dots {
		display: flex;
		justify-content: center;
		gap: 10px;
		margin: 20px 0 0;
	}

	.djj-materials__dot {
		width: 8px;
		height: 8px;
		border-radius: 50%;
		border: 1px solid var(--djj-gold);
		background-color: transparent;
		animation: djj-materials-dot 22s ease-in-out infinite;
	}

	.djj-materials__dot--1 { animation-delay: 0s; }
	.djj-materials__dot--2 { animation-delay: 5.5s; }
	.djj-materials__dot--3 { animation-delay: 11s; }
	.djj-materials__dot--4 { animation-delay: 16.5s; }
}

/* Posventa */
.djj-services {
	padding: clamp(56px, 10vw, 120px) clamp(20px, 5vw, 48px);
	background: var(--djj-cream);
	text-align: center;
}

/* Separación vertical "estándar" del home en escritorio (2026-08-31,
   pedido explícito) — mismo `clamp(28px,5vw,60px)` que ya usan
   Catálogo/Materiales, reemplazando acá el `clamp(56px,10vw,120px)`
   original solo en escritorio; la regla base de arriba sigue mandando en
   móvil sin cambios. */
@media (min-width: 768px) {
	.djj-services {
		padding-top: clamp(28px, 5vw, 60px);
		padding-bottom: clamp(28px, 5vw, 60px);
	}
}

.djj-services__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: 40px;
	max-width: 1000px;
	margin: 0 auto 40px;
}

.djj-services__card {
	text-align: center;
}

/* Círculo navy + ícono lineal dorado — mismo mecanismo `mask-image` que el
   carrito/menú hamburguesa del header (sección 2 de este archivo): un
   `background-color` sólido recortado por la forma de un SVG en escala de
   grises, en vez de un ícono de fuente o una imagen de color fijo — así
   el ícono sigue la paleta de marca si `--djj-gold` cambia alguna vez. */
.djj-services__icon {
	position: relative;
	width: 64px;
	height: 64px;
	border-radius: 50%;
	background: var(--djj-dark);
	margin: 0 auto 20px;
}

.djj-services__icon::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 26px;
	height: 26px;
	background-color: var(--djj-gold);
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}

.djj-services__icon--droplet::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z'/%3E%3C/svg%3E");
}

.djj-services__icon--tool::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z'/%3E%3C/svg%3E");
}

.djj-services__icon--edit::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5z'/%3E%3C/svg%3E");
}

.djj-services__name {
	font-family: 'Cormorant Garamond', serif;
	font-size: 21px;
	color: var(--djj-dark);
	margin-bottom: 8px;
}

.djj-services__desc {
	font-family: 'Poppins', sans-serif;
	font-size: 14px;
	color: var(--djj-teal);
	opacity: 0.75;
	line-height: 1.6;
	max-width: 280px;
	margin: 0 auto;
}

.djj-services__whatsapp {
	display: inline-block;
	color: var(--djj-teal);
	font-family: 'Poppins', sans-serif;
	font-size: 14px;
	text-decoration: underline;
}

.djj-services__whatsapp:hover {
	color: var(--djj-gold);
}

/* Móvil: ícono a la izquierda, nombre+descripción suben a la altura del
   ícono y quedan alineados a la izquierda (antes: ícono arriba, texto
   centrado debajo, igual que escritorio) — pedido explícito del usuario.
   Grid en vez de flex: ícono, nombre y descripción son 3 hijos directos y
   SIN wrapper propio en el HTML — con `flex` los 3 habrían quedado en una
   sola fila (ícono | nombre | descripción, uno al lado del otro). El grid
   de 2 columnas x 2 filas deja el ícono ocupando ambas filas (columna 1) y
   nombre/descripción apiladas en la columna 2, sin tocar el HTML. */
@media (max-width: 767px) {
	.djj-services__card {
		display: grid;
		grid-template-columns: 64px 1fr;
		grid-template-rows: auto auto;
		column-gap: 16px;
		text-align: left;
	}

	.djj-services__icon {
		grid-column: 1;
		grid-row: 1 / 3;
		align-self: start;
		margin: 0;
	}

	.djj-services__name {
		grid-column: 2;
		grid-row: 1;
	}

	.djj-services__desc {
		grid-column: 2;
		grid-row: 2;
		max-width: none;
		margin: 0;
	}
}

/* Sobre nosotros */
.djj-story {
	padding: clamp(56px, 10vw, 120px) clamp(20px, 5vw, 48px);
	background: var(--djj-cream);
	display: flex;
	gap: 64px;
	align-items: center;
	flex-wrap: wrap;
}

.djj-story__content {
	flex: 1;
	min-width: 320px;
}

/* Página independiente "Sobre nosotros" (page-sobre-nosotros.php) — sin la imagen
   que antes acompañaba el texto en el home, el bloque de texto se centra a un
   ancho de lectura cómodo en vez de estirarse a todo el ancho del contenedor. */
.djj-story--page {
	justify-content: center;
}

.djj-story--page .djj-story__content {
	flex: none;
	width: 100%;
	max-width: 720px;
	margin: 0 auto;
}

.djj-story__eyebrow {
	font-size: 13px;
	letter-spacing: 3px;
	color: var(--djj-gold);
	text-transform: uppercase;
}

.djj-story__content h2 {
	font-size: 36px;
	color: var(--djj-dark);
	margin: 14px 0 24px;
	line-height: 1.15;
}

.djj-story__content p {
	font-size: 16px;
	line-height: 1.7;
	color: var(--djj-teal);
	opacity: 0.85;
	margin: 0 0 36px;
}

.djj-story__bullets {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: 20px;
}

.djj-story__bullet {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 13px;
	color: var(--djj-dark);
}

/* Página independiente "Promociones" (page-promociones.php) — 3 filas
   alternadas imagen/contenido, fondo oscuro. Sin fotografía real todavía:
   caja placeholder con borde punteado dorado (en vez del degradé
   teal→dark que ya usan las tarjetas de categoría sin foto —
   `.djj-catalog__image--placeholder` — que acá se perdería casi por
   completo contra este mismo fondo oscuro). */
.djj-promo {
	/* padding-top a 25px exactos, a pedido del usuario (antes clamp(56-120px),
	   igual que el resto de las secciones) — separado del resto del padding,
	   que se queda con los valores originales. */
	padding: clamp(56px, 10vw, 120px) clamp(20px, 5vw, 48px);
	padding-top: 25px;
	background: var(--djj-dark);
}

.djj-promo__rows {
	display: flex;
	flex-direction: column;
	gap: 80px;
	max-width: 1100px;
	margin: 0 auto;
}

.djj-promo__row {
	display: flex;
	align-items: center;
	gap: 64px;
}

/* Filas pares (2ª, 4ª, ...) invertidas — imagen a la derecha, contenido a
   la izquierda. */
.djj-promo__row--reverse {
	flex-direction: row-reverse;
}

.djj-promo__image {
	position: relative;
	flex: 1;
	min-width: 0;
	aspect-ratio: 4 / 3;
	background: rgba(244, 239, 231, 0.04);
	border: 1px dashed rgba(201, 162, 93, 0.35);
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: center;
}

.djj-promo__photo-label {
	font-family: 'Poppins', sans-serif;
	font-size: 13px;
	color: rgba(244, 239, 231, 0.4);
	text-align: center;
	padding: 20px;
}

/* Medallón — cuelga del borde EXTERIOR de la imagen (izquierdo cuando la
   imagen va a la izquierda, derecho cuando va a la derecha, ver el
   override de abajo para las filas invertidas), no siempre del mismo lado. */
.djj-promo__badge {
	position: absolute;
	top: -28px;
	left: -28px;
	width: 84px;
	height: 84px;
	border-radius: 50%;
	background: var(--djj-gold);
	color: var(--djj-dark);
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: 'Cormorant Garamond', serif;
	font-size: 30px; /* x2, pedido explícito del usuario (era 15px) */
	font-weight: 600;
	text-align: center;
	line-height: 1.1;
	box-shadow: 0 8px 24px rgba(10, 26, 34, 0.5);
}

.djj-promo__row--reverse .djj-promo__badge {
	left: auto;
	right: -28px;
}

.djj-promo__content {
	flex: 1;
	min-width: 0;
}

.djj-promo__eyebrow {
	font-size: 12px;
	letter-spacing: 2px;
	color: var(--djj-gold);
	text-transform: uppercase;
	margin-bottom: 8px;
}

.djj-promo__content h3 {
	font-family: 'Cormorant Garamond', serif;
	font-size: 28px;
	color: var(--djj-cream);
	margin: 0 0 12px;
}

.djj-promo__content p {
	font-family: 'Poppins', sans-serif;
	font-size: 14px;
	line-height: 1.6;
	color: rgba(244, 239, 231, 0.7);
	margin: 0 0 20px;
	max-width: 420px;
}

.djj-promo__link {
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	font-weight: 600;
	color: var(--djj-cream);
	text-decoration: underline;
}

.djj-promo__link:hover {
	color: var(--djj-gold);
}

/* Catálogo de la categoría "promociones" (page-promociones.php) — mismo
   ancho/centrado que `.djj-promo__rows`, para quedar alineado con las 3
   filas de arriba. El grid en sí (`.woocommerce ul.products`, sección 10)
   no necesita nada nuevo acá — mismas tarjetas blancas del catálogo real. */
.djj-promo__catalog {
	max-width: 1100px;
	margin: 80px auto 0;
}

.djj-promo__legal {
	text-align: center;
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	color: rgba(244, 239, 231, 0.45);
	margin: 64px auto 0;
}

/* Móvil — mismo layout que escritorio (imagen + contenido lado a lado,
   alternando izquierda/derecha), a pedido explícito del usuario: la
   versión anterior apilaba imagen arriba / contenido debajo en una sola
   columna. `flex-direction: row`/`row-reverse` y `align-items: center` ya
   vienen heredados de la regla base (`.djj-promo__row`/`--reverse`), sin
   necesidad de repetirlos acá — solo se achican gap/medallón/tipografía
   para que quepan cómodos en un ancho de fila mucho más angosto (cada
   mitad, imagen y contenido, ronda los ~150px en un viewport de 375px). */
@media (max-width: 767px) {
	.djj-promo__row,
	.djj-promo__row--reverse {
		gap: 20px;
	}

	.djj-promo__rows {
		gap: 48px;
	}

	.djj-promo__badge,
	.djj-promo__row--reverse .djj-promo__badge {
		width: 48px;
		height: 48px;
		font-size: 16px; /* misma proporción que el medallón de escritorio (30px/84px), aplicada a este círculo más chico */
		top: -14px;
		left: -14px;
		right: auto;
	}

	.djj-promo__row--reverse .djj-promo__badge {
		left: auto;
		right: -14px;
	}

	.djj-promo__eyebrow {
		font-size: 10px;
		letter-spacing: 1.5px;
		margin-bottom: 4px;
	}

	.djj-promo__content h3 {
		font-size: 18px;
		margin: 0 0 6px;
	}

	.djj-promo__content p {
		font-size: 12px;
		line-height: 1.5;
		margin: 0 0 10px;
	}

	.djj-promo__link {
		font-size: 10px;
	}

	.djj-promo__photo-label {
		font-size: 10px;
		padding: 8px;
	}
}

/* Instagram */
.djj-instagram {
	padding: clamp(56px, 10vw, 120px) clamp(20px, 5vw, 48px);
	background: var(--djj-cream);
	text-align: center;
}

/* Separación vertical "estándar" del home en escritorio (2026-08-31,
   pedido explícito) — mismo criterio que `.djj-services`, ver ese
   comentario. Móvil sigue con la regla base, sin cambios. */
@media (min-width: 768px) {
	.djj-instagram {
		padding-top: clamp(28px, 5vw, 60px);
		padding-bottom: clamp(28px, 5vw, 60px);
	}
}

.djj-instagram h2 {
	font-size: 28.8px; /* -20% (2026-08-31, pedido explícito), antes 36px */
	color: var(--djj-dark);
	margin: 14px 0;
}

.djj-instagram__feed {
	max-width: 1100px;
	margin: 0 auto 44px;
}

/* Feed real de Smash Balloon (plugin "Instagram Feed"): oculta su propio
   header (avatar+bio) y su botón "Síguenos en Instagram" — la sección ya
   trae su propio eyebrow/h2/meta arriba y su propio botón "Seguir
   @dyj_joyeros" debajo; mostrar los dos duplicaría el mismo llamado a la
   acción. */
#sb_instagram .sb_instagram_header,
#sb_instagram .sbi_follow_btn {
	display: none !important;
}

/* Fondo transparente: se ve el fondo crema de la sección (`.djj-instagram`)
   detrás de las fotos, no un fondo propio del plugin. */
#sb_instagram {
	background: transparent !important;
	padding: 0 !important;
}

/* Mismas 3 columnas fijas en toda resolución que ya tenía el grid de
   placeholders (ver RESUMEN_SESION, grid de Instagram fijado a 3×2 en
   cualquier tamaño) — se pisan los breakpoints propios del plugin
   (640px/480px, no calzan con los 767px que usa el resto del tema) con el
   mismo valor en cualquier resolución, así no compiten entre sí. */
#sb_instagram #sbi_images {
	display: grid !important;
	grid-template-columns: repeat(3, 1fr) !important;
	gap: 12px !important;
	padding: 0 !important;
}

#sb_instagram .sbi_item {
	width: 100% !important;
}

/* Separador dorado translúcido entre fotos, igual que el resto de líneas
   divisorias del sitio, en vez de sin borde. */
#sb_instagram .sbi_photo_wrap {
	box-sizing: border-box;
	border: 1px solid rgba(201, 162, 93, 0.2);
}

/* Límite a las 9 publicaciones más recientes: el feed conectado (feed=1)
   trae su cantidad de fotos configurada en el admin del plugin (20) — el
   atributo `num` del shortcode NO la pisa cuando se usa `feed=<id>` (el
   plugin carga la configuración guardada del feed completa e ignora otros
   atributos, confirmado leyendo `class-sb-instagram-settings.php` por SSH:
   con `feed` presente en el shortcode, va directo a
   `get_settings_by_feed_id()`). Cambiar esa cantidad de forma "oficial"
   requeriría reproducir a mano el guardado completo del Feed Builder del
   plugin (formato interno no trivial, sin comando de WP-CLI para esto) —
   demasiado fràgil para un solo número. Se recorta a 9 por CSS en su lugar:
   las 20 fotos se siguen trayendo del feed, pero solo las primeras 9 se
   muestran. Con el límite fijo, ya no tiene sentido "Cargar más" (solo
   revelaría fotos ya traídas pero ocultas, nunca fotos nuevas) — se oculta
   junto con el resto de `#sbi_load` (incluye también el badge "Síguenos en
   Instagram", ya oculto arriba). */
#sb_instagram .sbi_item:nth-child(n + 10) {
	display: none !important;
}

/* Escritorio: 5 columnas × 2 filas (10 fotos) en vez de 3×3 (9) — a
   pedido explícito del usuario. Sube el límite de la regla de arriba en
   una foto más (`nth-child(n+10)` pasa de ocultar desde la 10 a
   mostrarla, y una nueva regla oculta recién desde la 11) y cambia las
   columnas del grid a 5. Móvil sigue en 3×3, con la regla base de
   arriba sin tocar. */
@media (min-width: 768px) {
	#sb_instagram #sbi_images {
		grid-template-columns: repeat(5, 1fr) !important;
	}

	#sb_instagram .sbi_item:nth-child(n + 10) {
		display: block !important;
	}

	#sb_instagram .sbi_item:nth-child(n + 11) {
		display: none !important;
	}
}

#sb_instagram #sbi_load {
	display: none !important;
}

/* Móvil: el fondo rotativo sigue usando el recorte "mobile" (más
   cerrado, ver `<source media>` en front-page.php) y el contenedor pasa
   de `min-height:480px` fijo a `aspect-ratio`.

   ⚠️ Primer intento, revertido el mismo día: `aspect-ratio:3/2`
   (paisaje) medía solo 213px de alto a 320px de ancho (teléfonos
   pequeños) — con el botón "Ver colección" + el resto del copy, eso
   desbordaba `overflow:hidden` en 17px reales (confirmado con
   `getBoundingClientRect`, no una suposición), cortando el borde
   inferior del botón. El usuario pidió invertir a `2:3` (retrato) en
   vez de agregar un alto mínimo de seguridad — a 320px de ancho, 2:3
   da 480px de alto, de sobra para el copy sin recortar nada.

   Los archivos `hero-bg-*-mobile.webp` se recortaron primero a
   562×843px (2:3 exacto) — encuadre centrado en la joya dentro del
   estuche abierto (no en el centro geométrico de la foto original, que
   incluye el jarrón y el estuche cerrado a los lados; con un recorte
   tan angosto, centrar en la foto completa cortaba el producto).

   2026-08-31 (mismo día): formato del contenedor pasa a `3/4` (pedido
   explícito) — ya no coincide con el 2:3 del recorte móvil de arriba.
   ⚠️ Dos intentos previos, los dos corregidos el mismo día: (1) dejar
   `object-fit:cover` heredado de la base recortaba la imagen arriba y
   abajo para llenar el nuevo formato ("se ven recortadas a lo alto");
   (2) `object-fit:contain` mostraba la imagen completa pero con una
   franja vacía a los lados — el usuario aclaró que el pedido real era
   **re-recortar las imágenes originales** (`Imagen Hero 1/2.png`,
   1862×845px, carpeta del usuario fuera del repo) para que calcen con
   el `3/4` desde el archivo mismo: alto = alto completo de la imagen
   (845px, sin perder nada verticalmente) y ancho recortado a 634px
   (845×3/4=633.75) centrado en la joya dentro del estuche abierto,
   mismo criterio de encuadre que el recorte 2:3 anterior. Con el
   archivo ya en el ratio correcto (634/845=0.7503, prácticamente
   3/4 exacto), `object-fit:cover` vuelve a la regla base sin
   override — el recorte que aplica ahora es < 1px, imperceptible. */
@media (max-width: 767px) {
	.djj-hero {
		aspect-ratio: 3 / 4;
		align-items: center;
		padding: 56px 20px;
	}

	.djj-hero__copy {
		max-width: none;
		left: 20px;
		bottom: 20px;
	}

	/* Categorías (home, sección #catalogo) a 2 columnas en vez de 1 sola —
	   el grid de escritorio usa minmax(240px,1fr), que en un viewport móvil
	   nunca deja espacio para una segunda columna. Se fuerzan 2 columnas
	   fijas y se baja el alto de imagen para que la tarjeta no quede
	   desproporcionadamente angosta y alta.

	   Separaciones a pedido explícito del usuario (2026-08-31): 5px del
	   borde lateral de la pantalla (antes heredaba el `clamp(20px,5vw,48px)`
	   de escritorio, sin override propio) y 10px entre tarjetas (antes
	   16px). */
	.djj-catalog {
		padding-left: 5px;
		padding-right: 5px;
		/* El padding-top a la mitad de arriba (2026-08-31) fue un pedido
		   explícito "en la versión de escritorio" — se restaura acá el
		   valor original para que móvil no herede el cambio sin querer. */
		padding-top: clamp(56px, 10vw, 120px);
		/* Mismo criterio para el padding-bottom unificado de arriba —
		   también "en la versión de escritorio". */
		padding-bottom: clamp(56px, 10vw, 120px);
	}

	.djj-catalog__grid {
		grid-template-columns: repeat(2, 1fr);
		gap: 5px; /* bajado de 10px a pedido del usuario, mismo día */
	}

	/* `height:160px` fijo eliminado (2026-08-31) — era la causa real de que
	   las imágenes no se vieran cuadradas en móvil (~180px de ancho real de
	   columna contra 160px de alto fijo). `aspect-ratio:1/1` en la regla
	   base (arriba) ya cubre este breakpoint también, sin necesitar ningún
	   valor fijo propio acá. */

	/* Materiales en móvil: ya no hay panel a la derecha (ese layout es solo
	   de escritorio) — el texto vuelve a quedar centrado y la foto pasa a
	   ancho completo de pantalla (sangrado, sin el padding lateral de la
	   sección), con puntos indicadores debajo sincronizados con el mismo
	   cross-fade (mismo `animation-delay` que cada foto, sin JS). */
	.djj-materials {
		padding-right: clamp(20px, 5vw, 48px);
		padding-bottom: 0;
	}

	.djj-materials .djj-heading {
		text-align: center;
		margin-bottom: 0;
	}

	.djj-materials__grid {
		position: relative;
		top: auto;
		right: auto;
		bottom: auto;
		height: auto;
		width: 100vw;
		margin: 15px calc(50% - 50vw) 0;
		aspect-ratio: 765 / 510;
		transform: none;
	}

	.djj-materials__dots {
		display: flex;
		justify-content: center;
		gap: 10px;
		margin: 16px 0 0;
	}

	.djj-materials__dot {
		width: 8px;
		height: 8px;
		border-radius: 50%;
		border: 1px solid var(--djj-gold);
		background-color: transparent;
		animation: djj-materials-dot 22s ease-in-out infinite;
	}

	.djj-materials__dot--1 { animation-delay: 0s; }
	.djj-materials__dot--2 { animation-delay: 5.5s; }
	.djj-materials__dot--3 { animation-delay: 11s; }
	.djj-materials__dot--4 { animation-delay: 16.5s; }
}

/* ==================== CATÁLOGO (archive-product) ==================== */

.woocommerce-page #primary,
.woocommerce-page .content-area {
	max-width: none;
	width: 100%;
	float: none;
	background: var(--djj-cream);
	/* 10px arriba (pedido explícito del usuario — antes había un hueco grande
	   entre el header y el contenido, ver nota debajo sobre la causa real). */
	padding-top: 10px;
	/* Izquierda/derecha: mismo valor que la separación entre productos
	   (`ul.products`, más abajo) — pedido explícito del usuario, "aplica la
	   misma separación... para los extremos de las pantallas". Antes
	   `clamp(20px,5vw,48px)` (48px a este ancho), sin relación con el gap
	   real entre tarjetas. 10px en móvil, ver @media más abajo. */
	padding-right: 15px;
	padding-bottom: clamp(48px, 9vw, 100px);
	padding-left: 15px;
	box-sizing: border-box;
}

@media (max-width: 767px) {
	.woocommerce-page #primary,
	.woocommerce-page .content-area {
		padding-right: 10px;
		padding-left: 10px;
	}
}

/* WooCommerce/Storefront insertan un <div class="woocommerce"> vacío justo
   antes de #primary en toda página de WooCommerce (archivo, carrito, etc.).
   La regla anterior (`.woocommerce.archive, .woocommerce-page .woocommerce`)
   sin querer apuntaba a DOS elementos a la vez: el <body> (que en archivo
   trae ambas clases "woocommerce" y "archive"), pisando su padding-top del
   header fijo (7.6) con el valor de acá; y este div vacío, que solo sumaba
   espacio en blanco sin ningún contenido real dentro. Se oculta el div vacío
   y el padding real se puso arriba, directo en #primary/.content-area. */
.woocommerce-page .woocommerce:empty {
	display: none;
}

.djj-catalog-back {
	margin-bottom: 12px;
}

.djj-catalog-back a {
	font-size: 12px;
	letter-spacing: 1.5px;
	color: var(--djj-teal);
	/* Sin subrayado — a pedido explícito del usuario. Mismo criterio que ya
	   tenía el link equivalente del checkout (.djj-checkout-panel__back),
	   que nunca llevó subrayado. */
	text-decoration: none;
	text-transform: uppercase;
}

.woocommerce-products-header {
	text-align: center;
	margin-bottom: 20px; /* 40px - 50%, a pedido del usuario (espacio entre el título "Anillos" y la barra de filtros) */
}

/* Escritorio: espacio título→filtros, corregido de verdad.
   ⚠️ Bug real — el primer intento (`margin-bottom:10px` sobre
   `.woocommerce-products-header` a secas) se veía "sin efecto" porque no
   era la única fuente del espacio: Storefront trae su PROPIA regla,
   `.storefront-full-width-content .woocommerce-products-header` (en
   `woocommerce.css` del tema padre), con `padding-bottom:5.99684em`
   (≈96px) — casi 5 veces más que el `margin-bottom` que se estaba
   editando, y con más especificidad (2 clases, 0-2-0) que la regla
   simple de acá (1 clase, 0-1-0), así que ganaba pese a cargar antes en
   el archivo. El espacio real percibido por el usuario era la SUMA de
   los dos (96px de padding + 20px de margin = 116px originales) — nunca
   se había tocado el padding, la fuente más grande de los dos. Fix:
   regla calificada con `body.storefront-full-width-content` (0-2-1,
   gana sin depender del orden de carga) que anula el padding de
   Storefront a 0 y fija el margin directo a 58px — la mitad exacta de
   los 116px originales, ahora sí. Solo acá, la regla base de arriba
   (móvil) sigue sin tocar. */
@media (min-width: 768px) {
	body.storefront-full-width-content .woocommerce-products-header {
		padding-bottom: 0;
		margin-bottom: 58px;
	}
}

.woocommerce-products-header__title.page-title {
	font-family: 'Cormorant Garamond', serif;
	font-weight: 500;
	font-size: 38px;
	color: var(--djj-dark);
	margin: 14px 0 0;
}

.woocommerce-result-count {
	font-family: 'Poppins', sans-serif;
	font-size: 13px;
	color: var(--djj-teal);
}

/* Storefront trae `.woocommerce-ordering`/`.woocommerce-result-count` con
   `float:left` nativo (woocommerce.css del tema padre) — en escritorio
   "flotan" uno junto al otro por casualidad de ancho disponible, pero en
   móvil el select (ya angosto, pero igual "ancho" en un viewport de 375px)
   no deja lugar al lado y el conteo cae a una fila propia debajo. A pedido
   del usuario: misma fila SIEMPRE, "Ordenar por" a la izquierda y el
   conteo de resultados pegado al borde derecho — se anula el float nativo
   con flexbox en el wrapper que ya imprime Storefront (`.storefront-sorting`),
   sin tocar ninguna plantilla.

   ⚠️ Bug real, encontrado al verificar en vivo — el conteo NO quedaba
   pegado al borde derecho (medido: ~213px de sobra a la derecha). Causa:
   `.storefront-sorting` trae un TERCER hijo, `.woocommerce-notices-wrapper`
   (vacío en el catálogo, WooCommerce lo imprime igual por si hace falta) —
   con `justify-content:space-between` sobre 3 ítems (no 2), el espacio se
   reparte en los DOS huecos entre ellos, corriendo "Ordenar por" hacia la
   derecha en vez de dejarlo pegado al borde izquierdo. Se saca ese wrapper
   vacío del flujo flex por completo. */
.storefront-sorting {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	/* ⚠️ Bug real, reportado por el usuario con captura — en escritorio, la
	   grilla de productos empezaba más abajo que la barra de filtros de la
	   barra lateral (~17px de diferencia real, medida antes de tocar nada).
	   Causa: Storefront trae `.storefront-sorting { margin-bottom: 2.61792em }`
	   nativo (woocommerce.css) — el mismo patrón de espaciado "de más" ya
	   encontrado varias veces en este archivo (formularios con `1.618em`),
	   acá sobre el propio contenedor, nunca anulado hasta ahora. Se
	   reemplaza por el mismo valor que ya separa el buscador de los
	   filtros en la barra lateral (`.djj-catalog-search`, `margin-bottom:
	   20px`) — mismo ritmo vertical en las 2 columnas, no un valor
	   calculado a mano aparte.

	   ⚠️ `!important` a propósito — misma especificidad (0,1,0) que la
	   regla nativa de Storefront, que carga después y gana el empate por
	   orden de carga; confirmado en vivo que sin `!important` el valor de
	   Storefront seguía ganando pese a `getComputedStyle` mostrar la regla
	   nueva "cargada" en `document.styleSheets`. */
	margin-bottom: 20px !important;
}

/* Fila "Ordenar por"/"0 resultados" forzada cuando no hay productos
   (djjoyeros_catalog_toolbar_when_empty(), functions.php) — pedido
   explícito del usuario: el aviso de "sin resultados" tiene que quedar
   DEBAJO de esta fila, no reemplazarla. Reutiliza la clase `.storefront-
   sorting` (misma fila que en el caso normal, con productos), solo se le
   suma este margen — en el caso normal esa separación la da el propio
   `ul.products` de abajo (padding/margin nativo), que acá no existe. */
.djj-catalog-toolbar--empty {
	margin-bottom: 16px;
}

.storefront-sorting .woocommerce-notices-wrapper:empty {
	display: none;
}

/* Storefront aplica un clearfix a `.storefront-sorting` (::before/::after con
   `content:""; display:table`, en woocommerce.css) pensado para su layout
   original con floats. Un flex container trata esos pseudo-elementos como
   DOS ítems más (0px de ancho) — con `justify-content:space-between` eso
   generó 3 huecos iguales en vez de 1 solo hueco entre "Ordenar por" y el
   conteo, empujando "Ordenar por" lejos del borde izquierdo. Ya no hace
   falta el clearfix (no quedan floats que limpiar: ambos hijos reales están
   en `float:none` arriba), así que se anulan estos pseudo-elementos.
   `!important` a propósito: misma especificidad (0,1,1) que la regla de
   woocommerce.css, que carga después y gana el empate por orden de carga
   (igual que ya pasó con `.woocommerce-ordering`/`.woocommerce-result-count`
   más arriba, donde subir la especificidad SÍ alcanzó — acá no hay forma de
   subir especificidad sin arriesgar romper el propio selector). */
.storefront-sorting::before,
.storefront-sorting::after {
	content: none !important;
	display: none !important;
}

/* Selector calificado con `.storefront-sorting` a propósito (no solo
   `.woocommerce-ordering`/`.woocommerce-result-count`): Storefront trae su
   propia regla `float:left; margin-right:1em` para estas clases en
   assets/css/woocommerce/woocommerce.css, con la MISMA especificidad
   (0,1,0) que una regla sin calificar — y esa hoja de WooCommerce carga
   después de la del tema hijo, ganando el empate por orden de carga (mismo
   patrón que ya se documentó en otros puntos de este archivo). Calificar
   con `.storefront-sorting` sube la especificidad a (0,2,0) y gana sin
   depender del orden de carga. */
.storefront-sorting .woocommerce-ordering,
.storefront-sorting .woocommerce-result-count {
	float: none;
	margin: 0;
}

/* Mismo formato visual que los desplegables de Talla/Material (10.4/§ filtros)
   — el select nativo de "Ordenar" no tenía ningún estilo propio, se veía con
   el look por defecto del navegador (borde gris de sistema, sin radio).

   ⚠️ Histórico — el `width` en px (40%, 80%, 444px, 666px en vueltas
   sucesivas) nunca se aplicó de verdad sin calificar con `.storefront-sorting`:
   `woocommerce.css` de Storefront trae `.storefront-sorting select{width:auto}`,
   MISMA especificidad que `.woocommerce-ordering select` sin calificar (1
   clase + 1 elemento cada una) — y esa hoja carga después que la del tema
   hijo, ganando el empate (mismo patrón ya documentado varias veces en este
   archivo). Irónicamente, `width:auto` es exactamente lo que se pide ahora
   ("autoajustable según lo seleccionado") — así que en vez de pelear contra
   esa regla de Storefront, se declara acá mismo, explícito (para que quede
   documentado y no dependa de que la hoja de Storefront exista/cargue en
   ese orden). `max-width:none` se mantiene por las dudas, ya que Storefront
   TAMBIÉN trae un `select{max-width:100%}` genérico sin calificar que
   podría volver a capar el ancho si el select alguna vez queda dentro de un
   contenedor angosto. Sin ancho fijo, ya no hace falta una regla aparte
   para móvil (el auto-ajuste funciona igual en cualquier viewport). */
.storefront-sorting .woocommerce-ordering select {
	box-sizing: border-box;
	width: auto; /* respaldo inicial — el ancho real, ajustado a la opción SELECCIONADA en cada momento (no solo la más larga del menú, que es lo único que `width:auto` nativo logra por sí solo), lo fija `catalog-filters.js` con un `style.width` inline en cada cambio */
	max-width: none;
	height: 33.6px; /* 42px - 20% */
	padding: 0 12px;
	background: #FFFFFF;
	border: 1px solid rgba(14, 58, 67, 0.2);
	border-radius: 4px;
	font-family: 'Poppins', sans-serif;
	font-size: 11.2px; /* 14px - 20% */
	color: var(--djj-dark);
}

.storefront-sorting .woocommerce-ordering {
	min-width: 0; /* permite que el form (ítem flex) se achique si hiciera falta */
}

/* ---- Layout de 2 columnas del catálogo (djjoyeros_catalog_layout_open()/
   _main_open()/_close(), functions.php) ----
   Pedido explícito del usuario, SOLO escritorio: "Los filtros y el
   buscador van a salir en una barra lateral fija al lado izquierdo". En
   móvil, sin ningún estilo de acá (todo `display:block` nativo) — el
   mismo HTML se apila en el orden normal del documento: buscador → botón
   "Filtros" → filtros (colapsables) → "Ordenar por"/conteo → grilla →
   paginación, exactamente como antes de este cambio. */
/* ⚠️ Bug real, encontrado al verificar la barra lateral "fija" —
   `position:sticky` no hacía nada, la barra se desplazaba con el resto de
   la página como si fuera estática. Causa, confirmada recorriendo la
   cadena de ancestros con `getComputedStyle` en vivo (no asumida):
   Storefront trae `.site { overflow-x: hidden }` (protección genérica
   contra desbordes horizontales) — `.site` es un ancestro real de la
   barra lateral (`.hfeed.site`, envuelve TODO el contenido del sitio). El
   spec de CSS dice que fijar `overflow-x` en un valor que no sea
   `visible` fuerza el `overflow-y` COMPUTADO a `auto` aunque nunca se
   haya declarado (confirmado: `overflow-y` medía `auto`, no `visible`,
   pese a que ninguna regla real lo pone en `auto`) — y CUALQUIER ancestro
   con overflow distinto de `visible`, en cualquiera de los 2 ejes, rompe
   `position:sticky` en los descendientes (comportamiento real de los
   navegadores, no un bug de este sitio). Se anula, acotado a las páginas
   de catálogo (`body.woocommerce-page`, mismo selector que ya usa esta
   hoja de estilos para otros ajustes específicos del catálogo, sección
   10.1) — no se toca `.site` a nivel global, para no arriesgar la
   protección real contra desbordes horizontales en el resto del sitio. */
body.woocommerce-page .site {
	overflow-x: visible;
}

@media (min-width: 768px) {
	.djj-catalog-layout {
		display: flex;
		align-items: flex-start;
		gap: 40px;
	}

	/* `position:sticky` — "fija" (pedido del usuario): la barra lateral se
	   queda a la vista mientras se hace scroll por la grilla de productos,
	   en vez de desplazarse con el resto de la página. `top` calibrado
	   contra el alto REAL del header fijo del sitio (`73.75px`, el mismo
	   valor ya medido y usado en `body { padding-top }`, sección 7.6 —
	   reutilizado acá, no un número nuevo) para que la barra lateral quede
	   pegada justo debajo del header, sin superponerse ni dejar hueco. */
	.djj-catalog-sidebar {
		flex: 0 0 280px;
		width: 280px;
		position: sticky;
		top: 73.75px;
		max-height: calc(100vh - 73.75px - 24px);
		overflow-y: auto;
	}

	.djj-catalog-main {
		flex: 1 1 auto;
		min-width: 0;
	}
}

/* ---- Barra de búsqueda de producto (djjoyeros_catalog_search_bar) ----
   Sin tarjeta propia — pedido explícito del usuario: el buscador queda
   directo sobre el marfil de fondo de la página (mismo `--djj-cream` que
   ya trae `.woocommerce-page #primary`), no dentro de una caja blanca
   aparte. El marco visible es el de la cápsula en sí
   (`.djj-catalog-search__form`, más abajo), no este contenedor — por eso
   acá no queda ni `background` ni `border` ni `padding` propio (el
   padding horizontal de la página, heredado del contenedor real, ya deja
   la cápsula alineada con "Pulseras"/"< Volver" arriba). */
.djj-catalog-search {
	margin: 0 0 20px; /* pedido explícito del usuario: 20px hasta el botón "Filtros" de abajo */
}

/* Móvil: 20px se queda en 20px (pedido de la vuelta anterior), pero el
   espacio HASTA EL BOTÓN "FILTROS" se reduce a 10px — pedido explícito
   del usuario, solo para esta pantalla. En escritorio no aplica: el botón
   "Filtros" ni siquiera se ve ahí (ver más abajo), así que este margen es
   directamente el espacio hasta la barra de filtros de la barra lateral. */
@media (max-width: 767px) {
	.djj-catalog-search {
		margin-bottom: 10px;
	}
}

/* Un solo marco (no dos elementos separados) — pedido explícito del
   usuario: el botón de buscar tiene que quedar DENTRO del marco del campo,
   no al lado como una caja aparte. `overflow:hidden` recorta el botón (un
   `<button>` cuadrado por dentro) a la forma redondeada del marco en el
   borde derecho, en vez de necesitar que el botón mismo calcule su propio
   radio. Altura fija (42px) + `border-radius` igual a la mitad de esa
   altura (21px) en las 4 esquinas — es lo que da la forma de "cápsula"
   pedida: con un radio de exactamente altura/2, las esquinas de arriba y
   de abajo se juntan en un semicírculo perfecto en cada lado (bordes
   laterales circulares), mientras que arriba y abajo, entre esas dos
   esquinas, el borde queda recto (no hay curva posible ahí — solo hay
   "esquina" en las puntas). */
.djj-catalog-search__form {
	display: flex;
	align-items: stretch;
	width: 100%;
	height: 42px;
	/* ⚠️ Bug real, encontrado al verificar los 20px pedidos hasta el botón
	   "Filtros" — sin esto, el espacio real medía ~25.9px, no 20px.
	   Storefront trae `form { margin-bottom: 1.618em }` genérico (su
	   escala tipográfica, la misma proporción áurea que ya se documentó en
	   9.5 para otros elementos) — como `.djj-catalog-search` (el div
	   contenedor, sin borde ni padding propio desde el punto 1 de esta
	   misma vuelta) no tiene nada que lo separe de este `<form>`, ese
	   margen del form "atraviesa" al padre (margin collapsing con el hijo)
	   y GANA por ser mayor (25.888px) que el `margin-bottom:20px` que sí
	   se le puso al contenedor — confirmado midiendo con
	   `getComputedStyle`, no asumido. */
	margin: 0;
	box-sizing: border-box;
	border: 1px solid rgba(14, 58, 67, 0.2);
	border-radius: 21px;
	background: #FFFFFF;
	overflow: hidden;
}

@media (min-width: 768px) {
	.djj-catalog-search__form {
		max-width: 420px;
	}
}

/* El marco (arriba) es quien dibuja el borde — el campo en sí queda sin
   borde propio, transparente, para no duplicar la línea. */
.djj-catalog-search__form:focus-within {
	border-color: var(--djj-gold);
}

/* ⚠️ Bug real, encontrado al verificar — el "relleno" del marco no era
   blanco homogéneo, la mitad del lado del campo se veía gris. Causa,
   confirmada recorriendo `document.styleSheets` en vivo (no asumida):
   Storefront trae `input[type="search"]{background-color:#f2f2f2; padding:
   0.618047em; box-shadow:0 1px 1px rgba(0,0,0,.125) inset; ...}` — un
   selector de tipo+atributo, más específico ((0,1,1)) que una sola clase
   como `.djj-catalog-search__input` ((0,1,0)) — le ganaba a TODA esta
   regla (no solo al fondo: también pisaba el padding y agregaba una
   sombra interna que no se había pedido), sin importar que este archivo
   cargue antes. Mismo patrón de bug ya documentado varias veces en este
   proyecto (ver sección 19) — se resuelve calificando el selector con el
   propio marco (`.djj-catalog-search__form`, dos clases, (0,2,0)) en vez
   de agregar `!important`. */
.djj-catalog-search__form .djj-catalog-search__input {
	flex: 1 1 auto;
	min-width: 0;
	height: 100%;
	box-sizing: border-box;
	padding: 0 4px 0 20px; /* 20px a la izquierda (curva del marco), 4px a la derecha (contra el botón, que ya trae su propio espacio interno) */
	border: none;
	border-radius: 0;
	background: #FFFFFF;
	box-shadow: none;
	color: var(--djj-dark);
	font-family: 'Poppins', sans-serif;
	font-size: 14px;
	-webkit-appearance: none;
	appearance: none;
}

.djj-catalog-search__form .djj-catalog-search__input::placeholder {
	color: #8a8a8a;
}

.djj-catalog-search__form .djj-catalog-search__input:focus {
	outline: none;
	box-shadow: none;
}

/* Safari agrega un ícono nativo de "borrar" (la x) en los input[type=search]
   con su propio tamaño/posición — se quita para no competir visualmente con
   el botón de lupa propio, que ya cumple una función parecida al vaciar el
   campo y reenviar el formulario. */
.djj-catalog-search__input::-webkit-search-cancel-button {
	-webkit-appearance: none;
	appearance: none;
}

/* Botón DENTRO del marco (hermano del input, ambos dentro del mismo
   `.djj-catalog-search__form` — ver comentario de arriba), sin su propio
   borde ni fondo sólido — transparente, para leerse como parte del mismo
   marco en vez de una caja aparte pegada al lado. */
.djj-catalog-search__button {
	flex-shrink: 0;
	width: 44px;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	background: transparent;
	border: none;
	color: var(--djj-dark);
	cursor: pointer;
}

.djj-catalog-search__button:hover {
	color: var(--djj-gold);
}

.djj-catalog-search__button svg {
	width: 18px;
	height: 18px;
}

/* Botón "Filtros" — colapsa/expande la barra de filtros (djjoyeros_catalog_
   filters_toggle(), functions.php). Sin marco, mismo criterio visual que
   ".djj-catalog-back a" ("< Volver") — pedido explícito del usuario. */
.djj-filters-toggle {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 0 0 16px;
	padding: 0;
	background: transparent;
	border: none;
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	color: var(--djj-teal);
	cursor: pointer;
	/* ⚠️ Reportado por el usuario — seguía quedando "marcado" tras tocarlo
	   en móvil, pese a la regla global de 7.11 (`button:focus{outline:
	   none}`). Mismo fix ya confirmado necesario en las flechas de
	   #catalogo-genero (10.24l): esa regla global sola no alcanza en
	   algunos navegadores/versiones de Android — hace falta sacar el
	   `<button>` del "chrome" nativo del sistema (`-webkit-appearance`/
	   `appearance:none`), apagar el flash táctil de Safari/Chrome Android
	   (`-webkit-tap-highlight-color`, un efecto de compositor que
	   `outline:none` no cubre) y cubrir `:focus`/`:focus-visible`/`:active`
	   por separado en vez de asumir que uno alcanza para los 3. */
	outline: none;
	-webkit-tap-highlight-color: transparent;
	-webkit-appearance: none;
	appearance: none;
}

.djj-filters-toggle:focus,
.djj-filters-toggle:focus-visible,
.djj-filters-toggle:active {
	outline: none;
	background: transparent;
	box-shadow: none;
}

/* El glifo es el mismo "<" de "< Volver" — rotado con CSS para apuntar
   hacia abajo (colapsado) en vez de redibujarlo como flecha nueva, pedido
   explícito del usuario. Gira otros 180° (apunta hacia arriba) cuando
   `.is-open` está presente — mismo estado que abre la barra de filtros. */
.djj-filters-toggle__arrow {
	display: inline-block;
	transform: rotate(-90deg);
	transition: transform 0.2s ease;
}

.djj-filters-toggle.is-open .djj-filters-toggle__arrow {
	transform: rotate(90deg);
}

/* Escritorio: sin botón "Filtros" — pedido explícito del usuario, "los
   filtros no serán desplegables, estarán visibles todo el tiempo" (no
   hay nada que desplegar/colapsar, así que el botón no tiene función). */
@media (min-width: 768px) {
	.djj-filters-toggle {
		display: none;
	}
}

/* ---- Barra de filtros (rango de precio, Talla, Material, limpiar) ----
   Todo generado por widgets nativos de WooCommerce (WC_Widget_Price_Filter,
   WC_Widget_Layered_Nav) vía the_widget() en functions.php — este bloque
   solo reestila su HTML/markup nativo, no inventa nada nuevo.

   Oculta por defecto (`display:none`) — pedido explícito del usuario, el
   botón "Filtros" de arriba la revela agregándole `.is-open`
   (assets/js/catalog-filters.js). Sin relación con si hay o no filtros
   activos: aunque el usuario ya haya elegido un Material, por ejemplo, la
   barra sigue arrancando oculta en cada carga de página — mismo criterio
   que ya usa el resto de este catálogo (Talla/Material/Precio tampoco
   "recuerdan" nada entre cargas). */
.djj-filters {
	box-sizing: border-box;
	background: #FFFFFF;
	border: 1px solid rgba(14, 58, 67, 0.1);
	padding: 24px clamp(20px, 5vw, 48px);
	margin: 0 0 16px; /* antes 32px — a pedido del usuario, otra fila con más de 10px de separación real que había quedado sin revisar en el pulido anterior (esta no es row-gap/column-gap, es el margin-bottom del propio bloque .djj-filters completo, contra la fila de "Ordenar por") */
	/* Oculta por defecto — `.is-open` (más abajo) la vuelve a `flex`. Sin
	   `!important`: el resto de las propiedades de esta regla (padding,
	   gap, etc.) se queda EXACTAMENTE igual que antes de este cambio (misma
	   especificidad de siempre, incluida la que ya usa el media query de
	   767px más abajo) — solo `display` cambia de estado, con una regla
	   aparte de mayor especificidad (2 clases) para no tener que duplicar
	   ni reordenar nada del resto del bloque ya afinado. */
	display: none;
	align-items: flex-end;
	gap: 24px;
}

.djj-filters.is-open {
	display: flex;
}

/* Escritorio: SIEMPRE visible, sin depender de `.is-open` — pedido
   explícito del usuario, "los filtros no serán desplegables, estarán
   visibles todo el tiempo". `!important` necesario para ganarle al
   `display:none` de la regla base de arriba, que no tiene ninguna
   condición de ancho — sin él, con los filtros arrancando SIEMPRE
   ocultos (`.is-open` es una clase que solo agrega el JS del toggle
   móvil, nunca presente de entrada), quedarían ocultos en escritorio
   también hasta que alguien los abriera manualmente — que es justo lo
   que este punto pide evitar. */
@media (min-width: 768px) {
	.djj-filters {
		display: flex !important;
	}
}

/* ⚠️ Bug real, reportado por el usuario — "dañaste la estética de los
   filtros en móvil". Estas reglas se habían agregado SIN media query
   (calificadas solo con `.djj-catalog-sidebar`, 2 clases) — como esa
   barra lateral es el MISMO wrapper en los 2 anchos (móvil y escritorio,
   ver `djjoyeros_catalog_layout_open()`), su mayor especificidad (0,2,0)
   le ganaba a las reglas móviles ya afinadas de más abajo (`.djj-filter--
   talla`/`--material`/`--estilo { flex:0 0 130px }` dentro de
   `@media(max-width:767px)`, 1 clase, 0,1,0) SIN IMPORTAR que esas reglas
   fueran las pensadas a propósito para ese ancho — forzando el apilado de
   escritorio (una fila = un filtro, ancho completo) también en móvil, y
   rompiendo el diseño de varias rondas de pulido (etiqueta a la
   izquierda, recuadros angostos, Talla/Material uno al lado del otro,
   "Limpiar filtros" con su propio ancho). Esas reglas de móvil ya NO
   existen (rediseño 2026-09-10, ver `.djj-filter-accordion` más abajo) —
   con los 5 filtros pasando a ser el mismo checklist apilado en los 2
   anchos, este bloque de columna ya sirve para los 2 por igual, así que
   se le quita el `@media` que antes lo limitaba solo a escritorio
   (pedido explícito del usuario, "reemplaza los filtros de móvil por una
   versión similar a la de escritorio"). `.djj-catalog-sidebar` envuelve
   la barra de filtros en TODOS los anchos (ver
   `djjoyeros_catalog_layout_open()`), así que esto sigue aplicando
   siempre, sin excepción. */
.djj-catalog-sidebar .djj-filters {
	flex-direction: column;
	align-items: stretch;
	gap: 16px;
}

.djj-catalog-sidebar .djj-filters__row {
	flex-direction: column;
	align-items: stretch;
}

.djj-catalog-sidebar .djj-filter {
	flex: none;
	width: 100%;
	min-width: 0;
}

.djj-catalog-sidebar .djj-filter--price {
	flex: none;
	width: 100%;
	margin-right: 0;
}

/* "Limpiar filtros" (el botón con borde dorado, ver la regla de más
   abajo — se mantiene igual, solo se le agrega esto) a todo el ancho de
   la barra lateral, en vez de `align-self:flex-end` (pensado para el eje
   CRUZADO de una fila horizontal — acá, con `.djj-filters` en columna,
   ese mismo `align-self` alinearía el botón a la derecha en vez de
   abajo). */
.djj-catalog-sidebar .djj-filters__clear--outside {
	align-self: stretch;
	width: 100%;
}

/* "Aplicar filtros" hereda el mismo ancho completo que "Limpiar
   filtros" en la barra lateral, mismo motivo que la regla de arriba. */
.djj-catalog-sidebar .djj-filters__apply {
	width: 100%;
}

/* "Limpiar filtros" es hermano de .djj-filters__row (no un hijo más adentro
   de la fila) — así puede quedar apilado debajo en móvil sin heredar el
   scroll horizontal de los filtros (ver media query 767px). En escritorio,
   .djj-filters__row con flex:1 empuja el link al borde derecho igual que
   antes, sin necesitar margin-left:auto (eso solo hacía falta cuando el
   link vivía DENTRO de la fila). */
.djj-filters__row {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	align-items: flex-end;
	gap: 10px;
	flex-wrap: wrap;
}

.djj-filter {
	flex: 1 1 180px;
	min-width: 160px;
}

.djj-filter__label {
	font-size: 11px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	color: #8a8a8a;
	margin-bottom: 10px;
	font-family: 'Poppins', sans-serif;
}

.djj-filters__clear {
	flex-shrink: 0;
	align-self: center;
	color: var(--djj-dark);
	font-size: 13px;
	text-decoration: underline;
	white-space: nowrap;
	font-family: 'Poppins', sans-serif;
}

/* "Limpiar filtros" (`.djj-filters__clear--outside`) sin ningún filtro
   activo — el link ahora se imprime siempre en PHP (ver ese comentario),
   con esta clase extra cuando no hay nada que limpiar. Por defecto (acá,
   sin media query — rige en móvil) no existe visualmente ni ocupa
   espacio, igual que antes cuando directamente no se imprimía. El
   `@media (min-width:768px)` más abajo lo pisa de vuelta a un tamaño
   real (invisible) SOLO en escritorio — ahí es donde estaba el bug real
   de "los filtros se corren al filtrar" (ver ese comentario). */
.djj-filters__clear--outside-empty {
	display: none;
}

/* "Aplicar filtros" — pedido explícito del usuario (2026-09-10), ahora en
   los 2 anchos por igual (antes solo escritorio — rediseño de móvil
   2026-09-10, ver `.djj-filter-accordion` más abajo). Fondo oscuro
   sólido — es la acción PRIMARIA de la barra de filtros, a diferencia de
   "Limpiar filtros" (borde dorado, sin relleno, secundario) — pero
   mismas esquinas redondeadas y mismo alto que ese botón (30px,
   `.djj-filters__clear--outside` más abajo), pedido explícito posterior
   del usuario ("bordes redondeados y tamaño similar al de limpiar
   filtros"). */
.djj-filters__apply {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 30px;
	padding: 0 20px;
	background: var(--djj-dark);
	color: var(--djj-cream);
	border: none;
	border-radius: 6px;
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	text-align: center;
	cursor: pointer;
	/* +10px sobre el `gap:16px` que ya reparte `.djj-filters` entre sus
	   hijos (2026-09-10, pedido explícito del usuario: "agrega 10px más
	   a la separación del botón con el último filtro") — 26px reales
	   entre el último filtro (Categoría, cuando aplica) y este botón. */
	margin-top: 10px;
}

.djj-filters__apply:hover {
	background: var(--djj-teal);
}

/* Estado de carga (2026-09-11, vuelta 279/280) — el texto ya cambia a
   "Aplicando…" desde JS (catalog-filters.js); acá solo el look atenuado +
   el spinner giratorio, a mano porque este botón no es un `.button` nativo
   de WooCommerce y no hereda su ícono `::after` de carga. */
.djj-filters__apply.is-loading {
	opacity: 0.7;
	cursor: not-allowed;
	position: relative;
	padding-right: 38px;
}

.djj-filters__apply.is-loading::after {
	content: '';
	position: absolute;
	right: 14px;
	top: 50%;
	width: 13px;
	height: 13px;
	margin-top: -7px;
	border: 2px solid rgba(244, 239, 231, 0.35);
	border-top-color: var(--djj-cream);
	border-radius: 50%;
	animation: djj-filters-apply-spin 0.6s linear infinite;
}

@keyframes djj-filters-apply-spin {
	to {
		transform: rotate(360deg);
	}
}

/* Escritorio: el slider de precio pasa a ocupar 1/3 del ancho de
   `.djj-filters__row`, en vez de crecer libre con `flex:1` (regla
   genérica `.djj-filter`) y absorber todo el espacio que Talla/Material/
   Estilo no usan (a 1280px de ancho, por ejemplo, llegaba a ~791px de
   791+130+130 — más de las 3/4 partes de la fila) — pedido explícito del
   usuario. `flex-grow:0` para que no vuelva a estirarse de más. */
/* `.djj-filter--price`/`.djj-filters__row` de acá abajo quedan sin efecto
   real hoy: `.djj-catalog-sidebar .djj-filter{flex:none;width:100%}` (ver
   más arriba) tiene mayor especificidad y gana siempre, en los 2 anchos
   — se dejan documentadas tal cual estaban (no se tocan) para no alterar
   nada que no haga falta; el motivo real de sacarlas de acá era liberar
   `.djj-filters__clear--outside` (más abajo) del `@media(min-width:768px)`
   que las envolvía a las 3 juntas, para que ese botón se vea igual en
   los 2 anchos (rediseño de móvil 2026-09-10, pedido explícito del
   usuario). */
.djj-filter--price {
	flex: 0 1 33.333%;
}

.djj-filters__row {
	gap: 30px;
}

.djj-filter--price {
	margin-right: 20px;
}

/* "Limpiar filtros" — mismo botón con borde dorado y esquinas
   redondeadas en los 2 anchos (antes solo escritorio, rediseño de móvil
   2026-09-10, pedido explícito del usuario: "reemplaza los filtros de
   móvil por una versión similar a la de escritorio"). Alto igual al de
   "Aplicar filtros" (30px), alineado contra el borde inferior de la fila
   (`align-self:flex-end`) en vez del `align-self:center` genérico de
   `.djj-filters__clear`. */
.djj-filters__clear--outside {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	align-self: flex-end;
	height: 30px;
	padding: 0 20px;
	border: 1.5px solid var(--djj-gold);
	border-radius: 6px;
	text-decoration: none;
	white-space: nowrap;
	/* -20% sobre el `gap:16px` que ya reparte `.djj-filters` entre sus
	   hijos (2026-09-10, pedido explícito del usuario: "reduce 20% la
	   separación entre los dos botones") — 16px×0.8 = 12.8px reales
	   entre "Aplicar filtros" y este botón; el margen negativo resta
	   los 3.2px que faltan para llegar a ese valor. */
	margin-top: -3.2px;
}

/* Bug real (reportado por el usuario, "los filtros se mueven a la
   izquierda al filtrar") — ver el comentario largo en PHP, junto a
   donde se imprime este link. Sin filtros activos, este botón ahora se
   imprime igual (antes no existía en el DOM) pero queda invisible sin
   perder su lugar en la fila — `visibility:hidden` (no `display:none`,
   que sí lo sacaría del layout) — así `.djj-filters__row`, al lado,
   nunca cambia de ancho entre tener y no tener un filtro activo. En los
   2 anchos por igual desde el rediseño de móvil de 2026-09-10 (antes
   solo escritorio). */
.djj-filters__clear--outside-empty {
	display: inline-flex;
	visibility: hidden;
	pointer-events: none;
}

/* ---- Acordeón "desplegable" por filtro (Talla/Material/Estilo/
   Colección/Categoría) — rediseño de móvil 2026-09-10, pedido explícito
   del usuario: "reemplaza los filtros de móvil por una versión similar a
   la de escritorio (selección múltiple, no se aplican hasta dar clic en
   Aplicar filtros, mismo orden/distribución) — evidentemente se debe
   mantener que sea desplegable, lo que debe cambiar es el orden visual y
   lógica después de expandir el filtro". Antes de esto, móvil mostraba un
   `<select>` de selección única por filtro y escritorio un checklist
   siempre visible — 2 componentes distintos. Ahora es el MISMO checklist
   en los 2 anchos (ver djjoyeros_render_checklist() y equivalentes en
   functions.php), envuelto en su propio acordeón
   (djjoyeros_filter_accordion_open()/_close()) — mecanismo calcado del
   acordeón del footer (`#colophon .djj-footer-accordion`, ver esa
   sección): el botón es el título simple, sin interacción, en escritorio
   (siempre expandido) y el disparador real del desplegable en móvil
   (colapsado por defecto). Mismo criterio que ya usa `.djj-filters` como
   conjunto contra el botón "Filtros" de arriba. */
.djj-filter-accordion__toggle {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	gap: 6px;
	margin: 0 0 10px;
	padding: 0;
	background: transparent;
	border: none;
	font-family: 'Poppins', sans-serif;
	font-size: 11px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	color: #8a8a8a;
	text-align: left;
	cursor: pointer;
	outline: none;
	-webkit-tap-highlight-color: transparent;
	-webkit-appearance: none;
	appearance: none;
}

.djj-filter-accordion__toggle:focus,
.djj-filter-accordion__toggle:focus-visible,
.djj-filter-accordion__toggle:active {
	outline: none;
	background: transparent;
	box-shadow: none;
}

/* Mismo glifo "‹" del acordeón del footer, rotado con CSS — apunta hacia
   abajo (colapsado) por defecto y gira 180° (hacia arriba) con
   `.is-open`, mismo estado que agrega/quita catalog-filters.js. */
.djj-filter-accordion__arrow {
	display: inline-block;
	flex-shrink: 0;
	color: var(--djj-gold);
	transform: rotate(-90deg);
	transition: transform 0.2s ease;
}

.djj-filter-accordion__toggle.is-open .djj-filter-accordion__arrow {
	transform: rotate(90deg);
}

/* Colapsado por defecto — solo móvil, el `@media` de abajo lo vuelve a
   mostrar siempre en escritorio, sin depender de `.is-open`. */
.djj-filter-accordion__panel {
	display: none;
}

.djj-filter-accordion__panel.is-open {
	display: block;
}

/* Escritorio: siempre expandido, título simple sin interacción real
   (aunque el botón siga técnicamente recibiendo el clic) — mismo
   criterio que ya usa `#colophon .djj-footer-accordion__toggle`. */
@media (min-width: 768px) {
	.djj-filter-accordion__toggle {
		cursor: default;
	}

	.djj-filter-accordion__arrow {
		display: none;
	}

	.djj-filter-accordion__panel {
		display: block;
	}
}

/* Móvil: la fila de filtros pasa a apilarse en una sola columna de ancho
   completo, igual que ya hace `.djj-catalog-sidebar .djj-filters__row`
   en escritorio (más arriba, ya sin `@media` — un solo layout para los 2
   anchos). Precio se separa de los acordeones con un poco más de aire
   (`row-gap`), y cada acordeón se distingue del siguiente con una línea
   divisoria fina, mismo criterio visual que ya usa el acordeón del
   footer entre sus filas. */
@media (max-width: 767px) {
	.djj-filters__row {
		row-gap: 20px;
	}

	.djj-filter-accordion {
		border-top: 1px solid rgba(14, 58, 67, 0.1);
		padding-top: 14px;
	}
}

/* Rango de precio — widget nativo WC_Widget_Price_Filter. La estructura real
   es <div class="price_slider_wrapper"><div class="price_slider">(slider)</div>
   <div class="price_slider_amount">(valores + botón "Filtrar")</div></div>.
   El slider en sí lo arma jQuery UI (clases .ui-slider-*) — por defecto NO
   hay auto-submit al soltar el drag (confirmado leyendo price-slider.js del
   propio plugin: solo actualiza los valores mostrados y los inputs ocultos,
   el filtrado real lo hace el <form method="get"> nativo al enviarse). A
   pedido del usuario, se agregó el envío automático al soltar el slider vía
   JS propio (`assets/js/catalog-filters.js`) — el botón "Filtrar" se dejó
   visible igual (sirve de respaldo si JS falla, y como confirmación visual
   de que hay un botón "de verdad" ahí, no solo decorativo).

   ⚠️ Se probó antes invertir el orden visual (valores arriba, slider abajo)
   con flexbox (column-reverse) en .price_slider_wrapper — el usuario reportó
   el slider invisible en escritorio y móvil, y no se pudo confirmar ni
   reproducir el problema por DOM/CSSOM (todo medía correctamente). Se
   revirtió esa reordenación por completo: menos superficie para que algo
   salga mal es más valioso acá que el orden visual exacto pedido en el
   diseño. El slider queda en su orden NATIVO (primero el slider, los valores
   debajo), sin display:flex ni reorder en el wrapper. */
/* ⚠️ Bug real, encontrado a pedido del usuario ("alinea los precios con los
   bordes del slider") — antes NO estaban alineados, por dos causas
   distintas, confirmadas midiendo con getBoundingClientRect antes de tocar
   nada:
   1. El slider (`.price_slider.ui-slider` más abajo) tiene `margin:8px 8px
      4px` — queda 8px más adentro que el resto del wrapper. `.price_slider_amount`
      no tenía ese mismo margen, así que su contenido arrancaba 8px más a la
      izquierda que el slider. Se le agrega el mismo margen horizontal.
   2. `.price_slider_amount` trae, además del `.price_label` visible, dos
      `<label class="screen-reader-text">` (para los inputs ocultos
      #min_price/#max_price) y un `<div class="clear">` — ninguno de los
      tres es `display:none` por defecto, así que SÍ cuentan como ítems flex
      y SÍ consumen `gap` real entre ellos, aunque no se vean (miden 0-1px).
      Eso le robaba ancho real a `.price_label` (confirmado: 779px medidos
      vs 791px del contenedor, exactamente el gap de 12px de uno de esos
      ítems fantasma). Se ocultan los tres — los labels no pierden nada de
      accesibilidad real, ya que los inputs que describen están `display:none`
      y por lo tanto ya inalcanzables para un lector de pantalla de todos
      modos. */
.djj-filter--price .price_slider_amount .screen-reader-text,
.djj-filter--price .price_slider_amount .clear {
	display: none;
}

.djj-filter--price .price_slider_amount {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin: 14px 8px 0;
}

.djj-filter--price .price_label {
	display: flex !important;
	flex: 1;
	justify-content: space-between;
	font-size: 12.75px; /* 15px - 15%, a pedido del usuario */
	font-weight: 500;
	color: var(--djj-dark);
	font-family: 'Poppins', sans-serif;
}

/* Botón "Filtrar" nativo, oculto — a pedido del usuario, revisado y
   confirmado sin uso práctico: los inputs de texto #min_price/#max_price que
   este botón enviaría están `display:none` (el propio JS de WooCommerce los
   esconde para mostrar el slider en su lugar, ver price-slider.js), así que
   el slider es la ÚNICA forma real de cambiar el precio — y el slider ya
   envía el formulario solo al soltar (`catalog-filters.js`, ver 10.4). Talla
   y Material tampoco lo necesitan (auto-envían nativo al cambiar). No se
   borra el botón en sí (es HTML nativo de WooCommerce, no una plantilla
   propia) — solo se oculta por CSS. */
.djj-filter--price .price_slider_amount .button {
	display: none;
}

.djj-filter--price .price_slider.ui-slider {
	position: relative;
	display: block;
	flex-shrink: 0;
	width: auto;
	height: 6px;
	background: #E5E0D8;
	border: none;
	border-radius: 3px;
	margin: 8px 8px 4px;
}

.djj-filter--price .ui-slider-range {
	position: absolute;
	top: 0;
	left: 0;
	height: 100%;
	background: var(--djj-gold);
	border-radius: 3px;
}

.djj-filter--price .ui-slider-handle {
	position: absolute;
	top: 50%;
	margin-top: -9px;
	margin-left: -9px;
	width: 18px;
	height: 18px;
	background: var(--djj-dark);
	border: 2px solid #FFFFFF;
	border-radius: 50%;
	cursor: pointer;
	outline: none;
	box-shadow: 0 1px 4px rgba(10, 26, 34, 0.4);
	z-index: 2;
}

/* Mismo margen fantasma de Storefront (`margin-bottom:1.618em`, heredado de
   Storefront como convención tipográfica general para <form>) en el
   `<form>` que envuelve el slider de precio (`.price_slider_wrapper`) —
   25.9px extra dentro de `.djj-filter--price` que no se ve pero corría el
   borde inferior real del bloque de precio, y por lo tanto el espacio hacia
   el resto de los filtros, muy por encima del `row-gap` de
   `.djj-filters__row`. Anulado para que ese `row-gap` sea, de verdad, el
   único responsable de ese espacio. */
.djj-filter--price form {
	margin-bottom: 0;
}

/* ---- Checklist de Material (djjoyeros_render_material_checklist()) ----
   Mismo componente en los 2 anchos desde el rediseño de móvil de
   2026-09-10 (antes, móvil mostraba un `<select>` de selección única) —
   envuelto en su propio acordeón "desplegable"
   (`.djj-filter-accordion`, ver esa sección más arriba), que es lo único
   que decide qué tan visible está en cada ancho. Sin ningún `display`
   propio acá — el checklist en sí siempre está en el DOM, listo para
   mostrarse en cuanto se expande su acordeón. */
.djj-material-checklist__form {
	margin: 0;
}

.djj-material-checklist {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.djj-material-checklist__item {
	display: flex;
	align-items: center;
	gap: 8px;
	font-family: 'Poppins', sans-serif;
	font-size: 13px;
	color: var(--djj-dark);
	cursor: pointer;
}

.djj-material-checklist__checkbox {
	width: 16px;
	height: 16px;
	margin: 0;
	accent-color: var(--djj-gold);
	cursor: pointer;
}

/* ---- Checklist de Sexo (djjoyeros_render_sexo_checklist()) ----
   Mismo mecanismo/CSS exacto que el checklist de Material de arriba
   (mismo acordeón `.djj-filter-accordion`, sin `display` propio acá),
   solo con la clase `--sexo` en vez de `--material`. */
.djj-sexo-checklist__form {
	margin: 0;
}

.djj-sexo-checklist {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.djj-sexo-checklist__item {
	display: flex;
	align-items: center;
	gap: 8px;
	font-family: 'Poppins', sans-serif;
	font-size: 13px;
	color: var(--djj-dark);
	cursor: pointer;
}

.djj-sexo-checklist__checkbox {
	width: 16px;
	height: 16px;
	margin: 0;
	accent-color: var(--djj-gold);
	cursor: pointer;
}

/* ---- Checklists genéricos: Talla/Estilo/Categoría (2026-09-03) ----
   Mismo mecanismo que Material/Sexo, pero generalizado
   (djjoyeros_render_checklist(), ver functions.php): los 3 comparten
   estas mismas clases `.djj-checklist*` (a diferencia de Material/Sexo,
   que tienen la suya propia cada uno) — mismo acordeón
   `.djj-filter-accordion` que decide la visibilidad en cada ancho, sin
   ningún `display` propio acá. */
.djj-checklist__form {
	margin: 0;
}

.djj-checklist {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.djj-checklist__item {
	display: flex;
	align-items: center;
	gap: 8px;
	font-family: 'Poppins', sans-serif;
	font-size: 13px;
	color: var(--djj-dark);
	cursor: pointer;
}

.djj-checklist__checkbox {
	width: 16px;
	height: 16px;
	margin: 0;
	accent-color: var(--djj-gold);
	cursor: pointer;
}

/* Máximo 4 columnas en escritorio (antes 6) — pedido explícito del
   usuario, después de que la grilla pasó a compartir ancho con la barra
   lateral fija (10.20): con el ancho real ya reducido por la barra
   lateral (280px + 40px de separación), 6 columnas quedaban demasiado
   angostas. El paso de 1279px de acá abajo queda en el mismo valor (4)
   por las dudas — sin efecto real hoy (nunca se activa un tope MÁS ALTO
   que este), pero documentado para no confundir a futuro. Bajando en 2
   pasos más hasta 1 en móvil angosto. */
.woocommerce ul.products {
	display: grid !important;
	grid-template-columns: repeat(4, 1fr);
	/* 15px en escritorio (antes 24px), a pedido explícito del usuario — se
	   mantiene igual en los pasos intermedios de 3 columnas (991px) más
	   abajo, que no trae su propio `gap`. */
	gap: 15px;
	margin: 0 0 40px;
	list-style: none;
}

/* WooCommerce trae su propio clearfix (::before/::after con content:"" y
   display:table) pensado para el layout original de floats. Al forzar
   display:grid arriba, esos pseudo-elementos pasan a contar como ítems
   REALES del grid (a diferencia de flex/block, en grid sí participan) — el
   ::before se auto-ubicaba en la columna 1, empujando el primer producto
   real a la columna 2 y dejando un hueco vacío a la izquierda. */
.woocommerce ul.products::before,
.woocommerce ul.products::after {
	content: none;
	display: none;
}

@media (max-width: 1279px) {
	.woocommerce ul.products {
		grid-template-columns: repeat(4, 1fr);
	}
}

@media (max-width: 991px) {
	.woocommerce ul.products {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (max-width: 767px) {
	/* 2 columnas hasta el angosto más chico — sin bajar a 1, mismo criterio
	   que las categorías del home (9.2): un solo breakpoint móvil. */
	.woocommerce ul.products {
		grid-template-columns: repeat(2, 1fr);
		gap: 10px; /* antes 16px, a pedido explícito del usuario */
	}

}

.woocommerce ul.products li.product {
	display: flex;
	flex-direction: column;
	width: 100% !important;
	margin: 0 !important;
	padding: 0;
	/* Fondo blanco → marfil, y se quita el marco azul petróleo (antes
	   `border: 1px solid var(--djj-teal)`, pedido explícito de una vuelta
	   anterior) — pedido explícito del usuario (2026-09-09), en dirección
	   contraria a esa vuelta: la tarjeta ya no lleva ningún marco. */
	background: var(--djj-cream);
	border: none;
	float: none;
	text-align: left;
}

.woocommerce ul.products li.product a.woocommerce-loop-product__link {
	display: flex;
	flex-direction: column;
	flex: 1;
	color: inherit;
}

.woocommerce ul.products li.product a {
	text-decoration: none;
	box-shadow: none;
}

.woocommerce ul.products li.product img {
	width: 100%;
	/* Cuadrada, pedido explícito del usuario (vuelta 110) — la foto fuente ya
	   es cuadrada (324×324), antes se recortaba a retrato 4:5 sin necesidad. */
	aspect-ratio: 1 / 1;
	height: auto;
	object-fit: cover;
	display: block;
	margin: 0;
	/* Se ve mientras no hay imagen real cargada (placeholder de WooCommerce
	   incluido) — un gris neutro, distinto del crema de fondo del sitio. */
	background: #EFEFEF;
}

/* `line-height` + `min-height` reservan siempre el alto de 2 líneas, sin
   importar si el nombre real ocupa 1 o 2 — reportado por el usuario:
   nombres de 2 líneas empujaban Material/Precio más abajo que en las
   tarjetas vecinas de nombre corto, desalineando esas filas entre sí en la
   misma fila de la grilla. Con el alto reservado, un nombre de 1 línea
   simplemente deja el espacio de la 2a línea vacío arriba (flujo de bloque
   normal, sin necesidad de centrar ni de JS) y Material/Precio quedan
   siempre a la misma altura entre tarjetas. */
.woocommerce ul.products li.product .woocommerce-loop-product__title {
	/* padding-top: 16px → 8px (2026-09-09, pedido explícito del usuario). */
	padding: 8px 16px 0;
	/* ⚠️ Bug real, reportado por el usuario — "veo una separación mayor a
	   5px entre el nombre y material" (2026-09-09). El `<h2>` nativo de
	   WooCommerce trae su propio `margin-bottom` (~10.3px, nunca anulado
	   hasta ahora) que se sumaba al `padding-top` de Material — el espacio
	   real terminaba siendo mayor al pedido. Confirmado midiendo
	   `getComputedStyle(title).marginBottom` en vivo antes de este fix. */
	margin-bottom: 0;
	font-family: 'Cormorant Garamond', serif;
	font-weight: 400;
	font-size: 19px;
	line-height: 1.25;
	/* `box-sizing:border-box` (reset global del tema) hace que `min-height`
	   cuente el `padding-top` como parte del total — sin sumarlo acá,
	   `2.5em` (2 líneas) le restaba ese padding al espacio real de texto y
	   el caso de nombre corto quedaba más bajo que uno de 2 líneas de
	   verdad, confirmado midiendo ambos con `getBoundingClientRect()`.
	   Ajustado junto con el padding-top de arriba, para que la reserva de
	   alto siga coincidiendo exacto con el padding real. */
	min-height: calc(2.5em + 8px);
	color: var(--djj-teal);
}

.djj-catalog-item__material {
	/* padding-top: 8px → 5px (2026-09-09, pedido explícito del usuario) —
	   el padding-top de acá ES el espacio completo, el título no tiene
	   ningún margin/padding propio abajo. */
	padding: 5px 16px 0;
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	color: rgba(14, 58, 67, 0.55);
}

.djj-catalog-item__material span {
	color: var(--djj-gold);
	font-weight: 500;
}

/* El espacio real entre el precio y el borde inferior de la tarjeta salía de
   DOS reglas sumadas: nuestro propio padding-bottom (20px, acá abajo) MÁS un
   margin-bottom:1rem (16px) nativo de Storefront (woocommerce.css) que nunca
   se había anulado — 36px combinados. Se deja solo el padding, más chico. */
.woocommerce ul.products li.product .price {
	padding: 8px 16px 8px;
	margin-bottom: 0;
	font-size: 16px;
	font-weight: 700;
	color: var(--djj-dark);
	font-family: 'Poppins', sans-serif;
}

.woocommerce ul.products li.product .price ins {
	text-decoration: none;
}

/* Precio de productos en promoción (djjoyeros_sale_price_html, functions.php)
   — sin selector de contenedor a propósito: el mismo filtro alimenta tanto
   la tarjeta del catálogo como la fila de compra de la ficha individual
   (.djj-product-purchase__buy .price), y en los dos casos el precio anterior
   y el actual deben quedar uno debajo del otro, alineados a la izquierda,
   con "Antes"/"Ahora" a la derecha de cada fila. */
.djj-price-sale {
	display: flex;
	flex-direction: column;
	gap: 2px;
	width: 100%;
}

.djj-price-sale__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
}

.djj-price-sale__row del {
	color: #E2401C;
	font-weight: 400;
	text-decoration: line-through;
	margin: 0;
}

/* !important en ambas — Storefront trae `.price ins { font-weight:400 }` en
   woocommerce.css (cargado DESPUÉS de este archivo), misma especificidad
   (1 clase + 1 tag) que este selector — empate que gana por orden de carga
   sin !important, mismo patrón ya visto muchas veces en este proyecto.
   `margin-left:9.89px` también nativo de Storefront (pensado para separar
   el precio actual del anterior cuando van EN LÍNEA, no apilados como acá). */
.djj-price-sale__row ins {
	font-weight: 700 !important;
	text-decoration: none;
	margin: 0 !important;
}

/* Mismo gris que "Material" en la tarjeta del catálogo
   (.djj-catalog-item__material). */
.djj-price-sale__label {
	font-size: 12px;
	font-weight: 400;
	color: rgba(14, 58, 67, 0.55);
	font-family: 'Poppins', sans-serif;
	text-decoration: none;
	flex-shrink: 0;
}

/* Sin botones "Ver detalles"/"Comprar" (a pedido del usuario) — toda la
   tarjeta es un solo link (woocommerce-loop-product__link, nativo) a la
   ficha del producto. Hover en la tarjeta completa como affordance de que
   es clicable, mismo criterio que las tarjetas de categoría del home. */
.woocommerce ul.products li.product {
	transition: box-shadow 0.2s ease;
}

/* Sin la tarjeta ya sin marco (ver arriba), el `border-color` que este
   `:hover` cambiaba antes no tenía ningún borde real que colorear — se
   quita, queda solo la sombra como affordance de "es clicable". */
.woocommerce ul.products li.product:hover {
	box-shadow: 0 4px 16px rgba(10, 26, 34, 0.12);
}

/* Sin líneas arriba/abajo del bloque de paginación — pedido explícito del
   usuario. */
.woocommerce nav.woocommerce-pagination,
.storefront-sorting {
	border-top: none !important;
	border-bottom: none !important;
}

/* ⚠️ Bug real, encontrado forzando el peor caso (50 páginas totales) para
   verificar el tope de recuadros — Storefront NO arma esta lista con
   flexbox (`display:block`, cada `<li>` en `inline-block`, ajuste de línea
   nativo de texto). `flex-wrap:nowrap` no tenía ningún efecto ahí (no es
   un contenedor flex) — en escritorio el peor caso (15 recuadros) igual
   entraba en 1 fila de pura casualidad (había ancho de sobra), pero en
   móvil (7 recuadros, ancho real ~345px) sí llegaba a partirse en 2
   líneas. Se fuerza `display:flex` acá para que el ajuste de línea sea
   controlable de verdad. */
.woocommerce nav.woocommerce-pagination ul {
	border: none;
	gap: 8px;
	display: flex;
	justify-content: center;
	width: 100%;
	box-sizing: border-box;
	/* Nunca pasar a una 2ª fila — pedido explícito del usuario ("máximo 1
	   fila"). Con el tope real de recuadros ya puesto en PHP
	   (`djjoyeros_catalog_pagination()`, máximo 15 en la versión de
	   escritorio de acá y 7 en la de abajo), el ancho disponible siempre
	   alcanza sin necesitar que los recuadros se encojan por debajo de su
	   `min-width` de 40px. */
	flex-wrap: nowrap;
}

/* La paginación se imprime 2 veces (`djjoyeros_catalog_pagination()`,
   functions.php) — una con hasta 15 recuadros para escritorio, otra con
   hasta 7 para móvil (WordPress/WooCommerce arman el HTML en el servidor,
   sin saber el ancho real de pantalla). Se muestra solo la que
   corresponde según el viewport, igual que "Limpiar filtros" (10.4c). */
.djj-pagination--mobile {
	display: none;
}

@media (max-width: 767px) {
	.djj-pagination--desktop {
		display: none;
	}

	.djj-pagination--mobile {
		display: block;
	}
}

/* ⚠️ Bug real, reportado por el usuario con captura de un dispositivo real
   (página 3 de una categoría con 9 páginas) — el último recuadro (flecha
   "siguiente") quedaba cortado fuera de la pantalla. Causa: un
   `margin-right: 4px` acá era pura redundancia con el `gap: 8px` del `ul`
   (arriba) — sumaban 12px reales entre recuadro y recuadro, no 8. El tope
   de 7 recuadros de `functions.php` se había verificado ÚNICAMENTE a
   375px (ancho del simulador de este proyecto, con solo 5px de margen
   real) — nunca contra un ancho más angosto pero igual de común en
   Android real, 360px, donde esos 12px de sobra hacían que la fila
   completa (352px) no entrara en el contenedor disponible (340px). Sin
   `margin-right` (sin tocar el tamaño de los recuadros, 40px, ni el
   `gap`) el espaciado real queda en los 8px que el CSS siempre dijo que
   eran, y recupera 24px en la fila de 7 — de -10px de margen real a
   +14px, verificado a 360px. */
.woocommerce nav.woocommerce-pagination ul li {
	border: none;
}

/* Páginas no seleccionadas (y la flecha de siguiente, misma clase
   `page-numbers`): recuadro azul petróleo, relleno marfil — pedido
   explícito del usuario, antes borde tenue sin relleno propio.
   `min-width` + `text-align:center` — sin esto, cada número quedaba con el
   ancho de su propio glifo ("1" más angosto que "2" con el mismo padding). */
.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
	border: 1px solid var(--djj-teal);
	background: var(--djj-cream) !important;
	color: var(--djj-teal) !important;
	font-family: 'Poppins', sans-serif;
	min-width: 40px;
	box-sizing: border-box;
	text-align: center;
}

/* Página seleccionada: relleno azul petróleo, texto dorado — antes era al
   revés (dorado de fondo). Mismo tratamiento en hover. */
.woocommerce nav.woocommerce-pagination ul li span.current,
.woocommerce nav.woocommerce-pagination ul li a:hover {
	background: var(--djj-teal) !important;
	color: var(--djj-gold) !important;
	border-color: var(--djj-teal) !important;
}

.woocommerce-info,
.woocommerce-message,
.woocommerce-noreviews,
p.no-products-found {
	font-family: 'Poppins', sans-serif;
	text-align: center;
	color: var(--djj-teal);
	background: transparent;
	border-top-color: var(--djj-gold);
	padding: 48px 0 !important;
}

/* ==================== FORMATO ESTÁNDAR DE MENSAJE DE ERROR ====================
   Nació como el recoloreo puntual de "No se encontraron productos"
   (categoría vacía), pero el usuario lo adoptó como el formato estándar
   para CUALQUIER mensaje de error del sitio — así que cubre también
   `.woocommerce-error`, la clase real que WooCommerce usa para errores de
   verdad (cupón inválido, campos de checkout sin completar, login
   fallido, etc.), no solo el aviso de categoría vacía. Fondo vinotinto,
   texto e ícono en blanco, ícono de exclamación centrado arriba, tipografía
   reducida, caja angosta (10px de padding vertical).

   Selectores por separado, no un solo grupo, porque cada uno necesita un
   comentario propio sobre POR QUÉ hace falta ese nivel de especificidad:

   — `.woocommerce-no-products-found .woocommerce-info`: el markup real es
     un `<div class="woocommerce-info">` anidado dentro de `<div
     class="woocommerce-no-products-found">` (dos elementos separados, no
     una sola clase combinada como asume el propio CSS de Storefront para
     este caso) — de ahí el selector con espacio. Selector de 2 clases a
     propósito, para no afectar otros avisos que reutilicen
     `.woocommerce-info` en otras partes del sitio, y para ganarle por
     especificidad a `woocommerce.css` de Storefront (cargado DESPUÉS de
     este archivo — ver el orden de enqueue en la sección 2), que trae
     `color:#fff` y `background-color:#3d9cd2` (un azul claro) para el
     mismo grupo genérico de clases de más arriba, con la misma
     especificidad (1 sola clase) — en ese empate gana quien carga después.
     ⚠️ Bug real encontrado al implementar el pedido original, no reportado
     antes: hubo que anular explícitamente tanto `color` como
     `background-color` — un primer intento que solo tocó `color` dejó el
     fondo azul nativo intacto por debajo, y el usuario lo reportó de
     nuevo.

   — `.woocommerce-error`: clase nativa de WooCommerce, viene como
     `<ul class="woocommerce-error" role="alert"><li>texto del error</li>
     ...</ul>` (uno o más `<li>`, confirmado con un cupón inválido real vía
     `wc-ajax=apply_coupon`) — nunca tenía estilo propio del tema hijo,
     usaba el rojo/naranja nativo de Storefront (`#e2401c`) sin relación
     con la marca. */
.woocommerce-no-products-found .woocommerce-info,
.woocommerce-checkout #payment .woocommerce-info,
.woocommerce-error {
	/* `!important` en background-color/border-radius: Storefront trae, en
	   `woocommerce.css` (cargado DESPUÉS de este archivo), una regla propia
	   y separada solo para `.woocommerce-error` (`background-color:#e2401c`,
	   el rojo nativo) y otra genérica con `border-radius:2px` — ambas con
	   la MISMA especificidad que esta regla (1 sola clase) y cargan después,
	   así que ganaban por orden de carga pese a que `color`/`padding`/
	   `text-align` de esta misma regla sí se aplicaban bien (Storefront no
	   los declara para `.woocommerce-error` en ningún lado). Confirmado
	   inyectando una respuesta real de error de checkout (`wc-ajax=checkout`
	   con campos vacíos) y midiendo con `getComputedStyle` — mismo patrón
	   de "hace falta !important" ya documentado varias veces en este
	   proyecto (ver sección 19). */
	background-color: #7A1E2C !important; /* vinotinto — no es parte de la paleta de marca (--djj-*), solo para mensajes de error */
	color: #FFFFFF;
	font-family: 'Poppins', sans-serif;
	font-size: 10.24px; /* 16px x0.8 x0.8 x0.8, ajustado en 3 vueltas sucesivas */
	text-align: center;
	border: none;
	border-radius: 0 !important; /* sin esquinas redondeadas, igual que el resto de los botones/cajas del sitio */
	list-style: none;
	/* La regla compartida de `.woocommerce-info` (más arriba) pone
	   `padding: 48px 0 !important` — y Storefront trae su propio padding
	   nativo para `.woocommerce-error` (`1em 2em 1em 3.5em`, pensado para
	   su ícono absoluto a la izquierda) — hace falta `!important` para
	   ganarle a ambos. 10px arriba del ícono y 10px abajo del texto/último
	   `<li>`, pedido explícito del usuario. */
	padding: 10px 0 !important;
}

.woocommerce-error li {
	list-style: none;
	margin: 0;
	padding: 0;
}

.woocommerce-error li + li {
	margin-top: 4px; /* separación entre errores, si el checkout devuelve más de uno */
}

/* Espacio entre el aviso de error y lo que sigue (ej. el eyebrow "Datos de
   envío", cuando faltan campos de facturación) — Storefront trae
   `margin-bottom:2.61792em` nativo para `.woocommerce-error`
   (woocommerce.css, misma especificidad que la regla compartida de arriba,
   cargado después) — resuelto contra el font-size YA reducido de esa regla
   (10.24px), da ~26.8px reales (medido con getBoundingClientRect, no
   asumido). Acotado al contexto del checkout — no toca el mismo aviso
   reutilizado en el catálogo ("no se encontraron productos"). */
body.woocommerce-checkout .woocommerce-error {
	margin-bottom: 8px !important;
}

.woocommerce-no-products-found .woocommerce-info::before,
.woocommerce-checkout #payment .woocommerce-info::before,
.woocommerce-error::before {
	/* Storefront trae su propio ::before para este grupo (ícono de Font
	   Awesome, `position:absolute;top:1.05em;left:1.5em`) — se anula
	   `content`/`display`/`position` explícitamente para dibujar acá un
	   ícono propio, centrado arriba del texto (no absoluto a la izquierda). */
	content: "";
	display: block !important; /* Storefront trae `display:inline-block` para este mismo ::before, misma especificidad, cargado después — con `inline-block` el `margin:0 auto` de abajo no centra nada (los márgenes automáticos no aplican a cajas inline-block), el ícono quedaba pegado a la izquierda */
	position: static !important; /* mismo motivo — Storefront trae `position:absolute` con la misma especificidad, cargado después — sin !important seguía absoluto, escapando del flujo normal en vez de quedar centrado arriba del texto */
	width: 28px;
	height: 28px;
	margin: 0 auto 12px;
	background-color: #FFFFFF; /* blanco, no vinotinto — sobre el fondo vinotinto de la caja necesita contraste */
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='12' y1='8' x2='12' y2='12'/%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'/%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='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='12' y1='8' x2='12' y2='12'/%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ==================== PRODUCTO INDIVIDUAL (single-product) ==================== */

.single-product #primary,
.single-product .content-area {
	max-width: none;
	width: 100%;
	float: none;
}

.single-product div.product {
	/* ⚠️ Bug real, reportado por el usuario ("sigo viendo más de 100px
	   entre 'volver' y la imagen") — el padding-top de acá (antes
	   `clamp(48px,9vw,100px)`, hasta 100px en escritorio) se sumaba al
	   margin de `.djj-catalog-back` (abajo), porque ese link no es
	   descendiente de `div.product` (son hermanos) — el fix de ese margin
	   por sí solo nunca alcanzaba. Bajado a un valor plano (sin `clamp`,
	   mismo criterio "un solo valor para escritorio y móvil") — el padding
	   inferior (espacio antes del footer) no se tocó. */
	padding: 20px clamp(20px, 5vw, 48px) clamp(48px, 9vw, 100px);
	background: var(--djj-cream);
	box-sizing: border-box;
	display: flex;
	flex-wrap: wrap;
	gap: 56px;
	max-width: 1100px;
	margin: 0 auto;
}

/* Móvil: 10px reales entre el marco de la galería (y el resto de la ficha)
   y los bordes de la pantalla — a pedido explícito del usuario. Antes el
   `clamp(20px,5vw,48px)` de arriba daba 20px de más, SUMADOS a los 10px
   que ya pone `.content-area` en este ancho — 30px totales en vez de los
   10px pedidos. Se deja en 0 acá porque `.content-area` ya cubre el
   estándar de 10px del resto del sitio en este ancho — no hace falta
   duplicarlo. Vertical (arriba/abajo) sin tocar. */
@media (max-width: 767px) {
	.single-product div.product {
		padding-left: 0;
		padding-right: 0;
		/* ⚠️ Bug real, reportado por el usuario con captura — quedaba mucho
		   espacio en blanco entre el marco dorado de la galería y el título
		   del producto. Causa: `gap:56px` (regla base, pensada para el
		   espacio HORIZONTAL entre galería y resumen en escritorio, lado a
		   lado) es un solo valor que en flexbox aplica igual al espacio
		   VERTICAL entre filas cuando el contenedor se envuelve — en móvil,
		   galería y resumen caen en filas separadas (`flex-wrap:wrap`, ya
		   no entran lado a lado) y heredaban ese mismo 56px como espacio
		   vertical entre ellas, sin que nadie lo hubiera pedido así. */
		gap: 10px;
	}
}

/* Mismo bug que el clearfix de ul.products (10.7-adyacente): WooCommerce
   trae ::before/::after con content:"" y display:table en div.product,
   pensados para su layout de floats — al ser display:flex acá, esos
   pseudo-elementos pasan a contar como ítems reales del flex (participan
   en flex-wrap y en el gap), sumando un espacio de más (~56px, el valor
   del gap) después del último ítem real (el resumen del producto). */
.single-product div.product::before,
.single-product div.product::after {
	content: none !important;
	display: none !important;
}

.single-product div.product .djj-catalog-back {
	flex-basis: 100%;
}

/* Espacio hacia la imagen, reducido — a pedido explícito del usuario, tanto
   en escritorio como en móvil (mismo valor en los dos, sin @media — antes
   12px, heredado de la regla genérica que comparte con la página de
   categoría).
   ⚠️ `.djj-catalog-back` NO es descendiente de `div.product` — lo imprime
   `woocommerce_before_main_content` (prioridad 15), ANTES de que WooCommerce
   abra `div.product` — es hermano de ese `div`, ambos hijos de
   `main.site-main`. Por eso el selector calificado por `body.single-product`
   (no por `div.product`) es el que hace falta acá. */
body.single-product .djj-catalog-back {
	margin-bottom: 4px;
}

.single-product div.product .woocommerce-product-gallery {
	flex: 1 1 380px;
	min-width: 280px;
}

/* Cuadrada, mismo criterio que la grilla del catálogo (pedido explícito del
   usuario, vuelta 110) — antes mostraba la imagen sin recortar, a la
   proporción original de cada foto (apaisada en algunos productos). */
.single-product div.product .woocommerce-product-gallery img {
	aspect-ratio: 1 / 1;
	object-fit: cover;
	/* ⚠️ Bug real, reportado por el usuario — franja vertical del color de
	   fondo dentro del marco dorado al cambiar de foto (más visible en la
	   2ª foto, de fondo distinto a la 1ª, pero el bug era el mismo en
	   ambas). Causa: sin `width`/`height` explícitos, `aspect-ratio` no
	   fuerza a la imagen a ocupar el ancho real de su diapositiva — el
	   navegador la deja en su tamaño intrínseco (el de cada archivo
	   subido), que casi nunca coincide exacto con el ancho real calculado
	   por FlexSlider para la diapositiva — la diferencia queda como franja
	   vacía a la derecha. `width:100%` + `height:100%` fuerza a la imagen a
	   llenar siempre su diapositiva real, sin importar la resolución del
	   archivo. */
	width: 100%;
	height: 100%;
	display: block;
}

/* ⚠️ Bug real, reportado por el usuario — el marco dorado quedaba
   "desfasado" al ver la segunda foto (la de la galería). Causa: el marco
   vivía en el `<img>` de CADA diapositiva individual, no en la ventana fija
   que las contiene — WooCommerce arma esta galería con FlexSlider, así que
   al cambiar de foto el marco se movía CON la imagen que se va, en vez de
   quedarse fijo enmarcando lo que se ve. Solución: el marco va en
   `.flex-viewport` (fijo, siempre presente aunque el producto tenga una
   sola foto), no en cada imagen. */
.single-product div.product .woocommerce-product-gallery .flex-viewport {
	border: 1.5px solid var(--djj-gold);
	/* Mismo bug de la franja vertical de arriba, visto desde el marco: sin
	   esto, FlexSlider fija el alto del marco por JS (`style="height:...px"`
	   inline, con su propia transición) a partir del tamaño intrínseco de
	   la 1ª foto — que puede no ser un cuadrado perfecto según el archivo
	   subido. `aspect-ratio:1/1` + `height:auto !important` (necesario
	   para ganarle al alto inline que pone FlexSlider) hace que el marco
	   sea SIEMPRE un cuadrado exacto según su propio ancho, sin depender
	   de la resolución de cada foto ni de qué diapositiva esté activa. */
	aspect-ratio: 1 / 1;
	height: auto !important;
}

/* El ícono de zoom (🔍, abre la galería a pantalla completa) trae
   z-index:99 nativo de Storefront (woocommerce.css) — empata con el header
   fijo (también 99, #masthead.site-header), y al hacer scroll el ícono
   queda visualmente por ENCIMA del header en vez de deslizarse por debajo.
   Bajarlo bien por debajo del header resuelve el solape sin tocar el
   z-index del header (que otros elementos ya usan como referencia base).
   ⚠️ El primer intento (`.single-product div.product .trigger`, 3 clases)
   no tuvo efecto: el selector real de Storefront
   (`.single-product div.product .woocommerce-product-gallery .trigger`,
   4 clases) es más específico y gana pese a cargar antes en la cascada —
   hubo que igualar exactamente esa cadena de selectores. Con la misma
   especificidad exacta, seguía ganando Storefront (`woocommerce.css` carga
   después del `style.css` del tema hijo) — hizo falta `!important`. */
.single-product div.product .woocommerce-product-gallery .woocommerce-product-gallery__trigger {
	z-index: 2 !important;
}

/* Móvil: miniaturas al costado derecho de la foto principal (antes debajo,
   a ancho completo) — a pedido explícito del usuario, para achicar la foto
   principal. No hace falta convertir `.woocommerce-product-gallery` en un
   contenedor flex (que movería también el ícono de zoom, posicionado
   `absolute` relativo A ESTE contenedor — ver comentario de arriba):
   alcanza con angostar `.flex-viewport` (dejándole un hueco a la derecha,
   del ancho exacto reservado para las miniaturas + su gap) y sacar
   `.flex-control-nav` del flujo normal con `position:absolute` para que
   ocupe ese hueco. El ícono de zoom recalcula su `right` para seguir en la
   esquina de la FOTO (más angosta ahora), no de todo el contenedor (que
   sigue midiendo el ancho completo de pantalla). `.flex-viewport` sigue
   siendo un cuadrado perfecto (`aspect-ratio:1/1`, arriba) — al angostarlo,
   se achica solo, sin tocar esa regla. */
@media (max-width: 767px) {
	.single-product div.product .woocommerce-product-gallery .flex-viewport {
		width: calc(100% - 64px);
	}

	.single-product div.product .woocommerce-product-gallery .woocommerce-product-gallery__trigger {
		right: calc(64px + 14px) !important;
	}

	.single-product div.product .woocommerce-product-gallery .flex-control-nav.flex-control-thumbs {
		position: absolute;
		top: 0;
		right: 0;
		width: 56px;
		display: flex;
		flex-direction: column;
		gap: 8px;
		margin: 0;
		padding: 0;
		list-style: none;
	}

	/* ⚠️ Bug real, encontrado verificando en vivo — las miniaturas salían
	   minúsculas (~5px), no 56px. Storefront trae su propia regla para la
	   MISMA cadena de selectores (`...woocommerce-product-gallery--columns-5
	   .flex-control-thumbs li`, en `assets/css/woocommerce/woocommerce.css`)
	   con la MISMA especificidad exacta (2 etiquetas + 5 clases) — pensada
	   para su layout nativo de 5 columnas con floats. Con especificidad
	   empatada, gana la que carga DESPUÉS en el HTML — confirmado
	   inspeccionando `document.styleSheets` directamente: ese
	   `woocommerce.css` de Storefront carga después del `style.css` del
	   tema hijo. `!important` hace falta para ganarle sin depender del
	   orden de carga. */
	.single-product div.product .woocommerce-product-gallery .flex-control-nav.flex-control-thumbs li {
		width: 100% !important;
		margin: 0 !important;
	}

	.single-product div.product .woocommerce-product-gallery .flex-control-nav.flex-control-thumbs img {
		width: 100%;
		aspect-ratio: 1 / 1;
		object-fit: cover;
		display: block;
		cursor: pointer;
	}
}

.single-product div.product .summary.entry-summary {
	flex: 1 1 320px;
	min-width: 280px;
}

/* WooCommerce/Storefront traen ~41.9px de margin-bottom nativo tanto en la
   galería como en .summary.entry-summary (misma escala de espaciado del bug
   7.5/8/9.2) — se suma al gap:56px del flex de arriba (duplicando el
   espacio entre galería y resumen) y, en el caso de .summary, queda además
   ENCIMA del padding-bottom propio de div.product, dejando un sobrante de
   espacio debajo de la fila de compra antes de que termine la ficha. */
.single-product div.product .woocommerce-product-gallery,
.single-product div.product .summary.entry-summary {
	margin-bottom: 0 !important;
}

.single-product .product_title.entry-title {
	font-family: 'Cormorant Garamond', serif;
	font-weight: 500;
	font-size: 30px;
	color: var(--djj-dark);
	margin: 0 0 16px;
}

.single-product .woocommerce-product-details__short-description {
	font-size: 14px;
	color: var(--djj-teal);
	opacity: 0.85;
	line-height: 1.6;
	margin-bottom: 16px;
}

.djj-product-meta__row {
	font-size: 13px;
	color: var(--djj-dark);
	opacity: 0.85;
	margin-bottom: 6px;
}

/* "Guía de tallas" — pedido explícito del usuario (2026-09-10), solo en
   fichas de Anillos, debajo de Material. Sin ninguna acción todavía (pedido
   explícito) — reset de `<button>` a look de link con ícono, mismo tono que
   `.djj-product-meta__row` de arriba. */
.djj-size-guide {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin: 0 0 6px;
	padding: 0;
	background: transparent;
	border: none;
	font-family: 'Poppins', sans-serif;
	font-size: 13px;
	color: var(--djj-dark);
	opacity: 0.85;
	cursor: pointer;
	outline: none;
	-webkit-tap-highlight-color: transparent;
	-webkit-appearance: none;
	appearance: none;
}

.djj-size-guide svg {
	width: 18px;
	height: 18px;
	flex-shrink: 0;
}

.djj-size-guide span {
	text-decoration: underline;
}

.djj-product-care {
	margin-top: 12px;
}

.djj-product-care__title {
	font-size: 13px;
	font-weight: 600;
	color: var(--djj-dark);
	margin-bottom: 8px;
}

.djj-product-care p {
	font-size: 13px;
	color: var(--djj-teal);
	opacity: 0.8;
	line-height: 1.6;
	margin: 0;
}

/* Espacio entre el párrafo de cuidado y el de garantía, cuando los dos
   existen (Oro/Oro laminado/Plata) — el segundo `<p>` no es un párrafo
   más, así que no hereda el `margin:0` pensado para uno solo. */
.djj-product-care p + p {
	margin-top: 8px;
}

.djj-product-purchase {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 20px;
}

/* Asesoría por WhatsApp + entrega + disponibilidad — a pedido del usuario,
   al final de toda la ficha, ya no junto al precio (ver
   `djjoyeros_product_info_block()`, functions.php). Se queda con el mismo
   divisor/espaciado que antes tenía `.djj-product-purchase` (era la última
   fila de la ficha entonces; ahora lo es este bloque). */
.djj-product-info {
	border-top: 1px solid rgba(14, 58, 67, 0.15);
	padding-top: 32px;
	margin-top: 32px;
}

.djj-product-purchase__whatsapp {
	font-size: 13px;
	letter-spacing: 0.5px;
	color: var(--djj-teal);
	text-decoration: underline;
}

.djj-product-purchase__delivery {
	font-size: 12px;
	color: var(--djj-teal);
	opacity: 0.7;
	margin-top: 8px;
}

/* Disponibilidad ("2 disponibles"), armada a mano en
   `djjoyeros_product_info_block()` — ya no la imprime WooCommerce (ver el
   filtro `woocommerce_get_stock_html` en functions.php), así que esta
   regla ya no depende del truco de `order`/`flex-basis` que hacía falta
   cuando vivía adentro del flex de precio+botón. */
.djj-product-info p.stock {
	margin: 8px 0 0;
	font-size: 13px;
	color: var(--djj-teal);
}

.djj-product-purchase__buy {
	display: flex;
	align-items: center;
	gap: 20px;
	flex-wrap: wrap;
}

.djj-product-purchase__buy .price {
	font-size: 20px;
	font-weight: 600;
	color: var(--djj-teal);
	/* WooCommerce imprime <p class="price"> con ~32px de margin simétrico
	   (arriba y abajo) por defecto; el <form class="cart"> de al lado no
	   trae margin-top, solo margin-bottom (~26px) — con align-items:center
	   del flex padre, ese desbalance de márgenes descentraba el precio
	   respecto al botón "Comprar" pese al centrado. !important porque el
	   selector nativo de WooCommerce que trae ese margin (más elementos +
	   clases) pesa más que este por especificidad pura. */
	margin: 0 !important;
}

.djj-product-purchase__buy .price ins {
	text-decoration: none;
}

.djj-product-purchase__buy .quantity {
	/* !important: WooCommerce le pone display en línea al elemento cuando
	   confirma la variación seleccionada (product-variation-layout.js la
	   auto-selecciona), y ese estilo en línea le gana a esta regla sin el
	   !important. */
	display: none !important;
}

.djj-product-purchase__buy form.cart {
	margin: 0 !important;
}

.djj-product-purchase__buy .single_add_to_cart_button {
	padding: 16px 32px;
	background: var(--djj-dark);
	color: var(--djj-cream);
	border: none;
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	font-family: 'Poppins', sans-serif;
	border-radius: 0;
}

/* Aviso "Este producto ya está en tu carrito." (functions.php,
   djjoyeros_prevent_duplicate_cart_item + cart-drawer.js) — mismo rojo que
   ya usan los errores en línea del checkout (#E2401C, ver 13.1), a ancho
   completo debajo de la fila de compra (no adentro del flex de precio+botón,
   para no descuadrar esa alineación). Oculto por defecto vía JS. */
.djj-add-to-cart-error {
	width: 100%;
	margin: 12px 0 0;
	font-size: 12.8px;
	color: #E2401C;
	display: none;
}

.djj-product-purchase__buy .single_add_to_cart_button:hover {
	background: var(--djj-teal);
}

/* Ficha de producto variable (Anillos, ver README 11.5/11.6): selector de
   Talla arriba del precio, precio+botón juntos como en las demás categorías.
   product-variation-layout.js mueve <table class="variations"> fuera del
   <form>, antes de <p class="price"> — así queda como un hijo flex más de
   .djj-product-purchase__buy, en su propia fila (order+flex-basis). El
   <form> (ya sin la tabla adentro) se queda como flex-item normal junto al
   precio: como todo lo demás que trae adentro está oculto, su tamaño
   visible termina siendo solo el del botón "Comprar".
   ⚠️ Se probó primero con display:contents en el <form> y sus wrappers
   intermedios (single_variation_wrap, woocommerce-variation-add-to-cart)
   para "promover" el botón a hijo directo del flex — funcionaba para el
   layout pero producía un salto de línea inconsistente entre precio y
   botón pese a sobrar espacio horizontal (aparente bug de flex-wrap con
   varios niveles de display:contents apilados). Sacar el <table> del
   <form> por JS y dejar el <form> como item normal (sin display:contents)
   resolvió el salto de línea sin perder nada del comportamiento. */
.djj-product-purchase__buy table.variations {
	order: -1;
	flex-basis: 100%;
	margin: 0 0 4px;
	border-collapse: collapse;
}

.djj-product-purchase__buy table.variations td {
	padding: 0;
	border: none;
}

.djj-product-purchase__buy table.variations select {
	font-family: 'Poppins', sans-serif;
	font-size: 13px;
	padding: 10px 14px;
	border: 1px solid var(--djj-gold);
	border-radius: 0;
	background: transparent;
	color: var(--djj-teal);
	min-width: 140px;
}

.djj-product-purchase__buy form.variations_form {
	margin: 0 !important;
}

/* Con una sola talla no hay nada que "limpiar" — el script ya la deja
   preseleccionada. Con más de una en el futuro, WooCommerce vuelve a exigir
   elegir explícitamente y esta regla deja de aplicar (el link solo aparece
   una vez hecha una selección real). */
.djj-product-purchase__buy .reset_variations_alert,
.djj-product-purchase__buy a.reset_variations {
	display: none;
}

/* El precio ya se muestra arriba (woocommerce_template_single_price, fijo
   para el único valor de esta talla) — sin este bloque se duplicaría al
   seleccionar la variación. !important: WooCommerce lo pone en línea
   (display:block) al confirmar la variación — sin el !important ese
   estilo en línea gana y el bloque (description/price/availability)
   agranda la caja del <form>, empujando visualmente el botón. */
.djj-product-purchase__buy .woocommerce-variation.single_variation {
	display: none !important;
}

/* WooCommerce inserta este link ("Ver carrito →") por su cuenta después de
   un add-to-cart exitoso — ya sea el flujo AJAX nativo del catálogo o, según
   se confirmó esta sesión, también en producto individual. Se había ocultado
   antes solo pensando que aplicaba al catálogo, y se sacó por error creyendo
   que era CSS muerto — la regla es GENERAL (sin acotar a un contenedor), no
   específica del catálogo. El drawer ya cumple esa función; es redundante
   en cualquier contexto donde aparezca. */
a.added_to_cart {
	display: none !important;
}

/* ==================== DRAWER DE CARRITO ==================== */

body.djj-cart-open {
	overflow: hidden;
}

.djj-cart-overlay {
	position: fixed;
	inset: 0;
	background: rgba(10, 26, 34, 0.6);
	z-index: 100;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.25s ease;
}

.djj-cart-overlay.is-open {
	opacity: 1;
	visibility: visible;
}

.djj-cart-drawer {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	width: 420px;
	max-width: 92vw;
	background: var(--djj-teal);
	z-index: 101;
	display: flex;
	flex-direction: column;
	transform: translateX(100%);
	transition: transform 0.3s ease;
}

/* El box-shadow vive SOLO acá, no en la regla de arriba — con el drawer
   "cerrado" (fuera de pantalla vía translateX(100%)), el desenfoque de 60px
   de la sombra igual alcanzaba a asomarse por el borde derecho de CUALQUIER
   página (el borde izquierdo del panel cerrado queda justo en el borde del
   viewport, así que el desenfoque de la sombra entra aunque el panel en sí
   no se vea) — se veía como una franja oscura y difusa pegada al borde
   derecho, de arriba a abajo, en toda página del sitio. Bug preexistente,
   nunca reportado hasta que se probó a fondo en dispositivo real esta sesión. */
.djj-cart-drawer.is-open {
	box-shadow: -20px 0 60px rgba(0, 0, 0, 0.4);
	transform: translateX(0);
}

.djj-cart-drawer__header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 17px 28px; /* vertical reducido ~20% del alto total, ver README */
	border-bottom: 1px solid rgba(201, 162, 93, 0.25);
	flex-shrink: 0;
}

.djj-cart-drawer__title {
	font-family: 'Cormorant Garamond', serif;
	font-size: 24px; /* -20% a pedido explícito del usuario — 30px × 0.8 */
	color: var(--djj-cream);
}

.djj-cart-drawer__close {
	background: none;
	border: none;
	cursor: pointer;
	color: var(--djj-gold);
	font-size: 24px;
	line-height: 1;
	padding: 0;
}

.djj-cart-drawer__body {
	flex: 1;
	overflow-y: auto;
	padding: 8px 28px 28px;
	/* Columna flex: la lista queda arriba con su alto natural, y el total+botón
	   (margin-top:auto en .woocommerce-mini-cart__total) se ancla abajo del todo,
	   dejando espacio vacío en medio cuando hay pocos ítems. */
	display: flex;
	flex-direction: column;
}

.djj-cart-drawer__body .woocommerce-mini-cart__empty-message {
	padding: 60px 0;
	text-align: center;
	color: rgba(244, 239, 231, 0.5);
	font-size: 14px;
}

.djj-cart-drawer__body ul.woocommerce-mini-cart {
	list-style: none;
	margin: 0;
	padding: 0;
	flex-shrink: 0;
}

/* CSS Grid en vez de flexbox para este ítem — con flexbox (`flex-wrap` +
   `order` + mezcla de `flex-basis: auto/0%/100%` entre nombre, precio e
   ícono) el motor de renderizado de este proyecto daba resultados erráticos
   e inconsistentes para decidir qué comparte línea con qué (ítems
   superpuestos, saltos de línea que no correspondían) — un patrón ya visto
   antes con auto-placement de grid (bugs 40/44) y ahora también con el
   "tamaño hipotético" de flex-wrap. Grid con columnas/filas EXPLÍCITAS no
   depende de ninguna heurística de "qué entra en la línea": */
.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item {
	display: grid;
	/* Reescrito (pedido explícito del usuario: mover el precio debajo del
	   nombre, alineado a su izquierda — antes 2 columnas (imagen+nombre |
	   precio), ambas en la misma fila).

	   ⚠️ Primer intento real (columna 1 = imagen con `grid-row:1/3` ocupando
	   nombre+precio, columna 2 = nombre/precio apilados) tenía un bug de
	   CSS Grid encontrado verificando en vivo: cuando un ítem (la imagen)
	   ocupa 2 filas `auto` y su alto (96px) supera lo que nombre+precio
	   necesitan en conjunto, el motor de Grid reparte el sobrante ENTRE las
	   2 filas que abarca — no lo dejaba como espacio vacío después de la
	   imagen, sino que agrandaba las 2 filas de texto por igual, separando
	   nombre y precio ~18px en vez de los 4px de `row-gap` pedidos (nombre
	   y precio, medidos por separado, sí mantenían su alto real de
	   contenido — el hueco de más aparecía siempre ENTRE los dos).

	   Solución real: sacar la imagen del grid por completo (`position:
	   absolute`, igual que ya se hace con el ícono de eliminar) y reservar
	   su espacio con un `padding-left` fijo (96px imagen + 10px separación)
	   en vez de una columna de grid — así nombre y precio quedan en una
	   sola columna de ancho completo, cada fila sizeada solo por su propio
	   contenido, sin que la imagen (que ya no participa del grid) infle
	   nada. */
	grid-template-columns: 1fr;
	row-gap: 4px;
	/* 10px reales entre la línea de separación y la imagen, arriba y abajo. */
	padding: 10px 0;
	/* Reserva el espacio de la imagen (96px + 10px de separación) sin que
	   la imagen participe del grid — ver el comentario de arriba. */
	padding-left: 106px;
	/* ⚠️ Bug real, reportado por el usuario — con un nombre largo (2 líneas),
	   el texto pasaba POR DEBAJO del ícono de eliminar (`position:absolute`,
	   fuera del grid, así que nunca angostaba el ancho disponible del texto
	   por su cuenta). Reserva el ancho real del ícono (32.4px) + separación
	   (10px, mismo criterio que el resto del espaciado de este `<li>`) en
	   TODO el ancho de la columna de texto (nombre y precio, no solo la
	   primera línea) — más simple y robusto que intentar que el texto
	   "abrace" al ícono solo en la línea 1. */
	padding-right: 42.4px;
	/* La imagen (96px) puede superar el alto real de nombre+precio juntos
	   (67px con textos cortos) — sin esto, el `<li>` se achicaría a ese
	   alto y la imagen (absoluta) se saldría por abajo, encima del
	   siguiente producto.
	   ⚠️ 116px, no 96 — este `<li>` hereda `box-sizing:border-box` (bug
	   real, encontrado verificando en vivo: con `min-height:96px` la
	   imagen, `position:absolute` con `top:10px`, terminaba en 106px desde
	   el borde superior real, pero el `<li>` con `border-box` interpreta
	   ese `min-height` como el alto TOTAL —incluido el padding—, no solo
	   el del contenido, así que se quedaba en 96px totales y la imagen se
	   salía 10px por debajo del propio borde/línea divisoria del `<li>`).
	   116 = 96 de imagen + 10px arriba + 10px abajo, el alto total real que
	   ya tenía la fila antes de este cambio. */
	min-height: 116px;
	border-bottom: 1px solid rgba(201, 162, 93, 0.15);
	/* Ancla real para la imagen y el ícono de eliminar, ambos
	   `position:absolute` (ver comentarios más abajo). */
	position: relative;
}

/* El <a> de WooCommerce envuelve la imagen Y el nombre juntos, sin wrapper
   propio para cada uno (mini-cart.php nativo) — `display:contents` le quita
   su propia caja de layout y "promueve" a sus 2 hijos (la imagen, y el
   `<span class="djj-cart-item-name">` que agrega djjoyeros_wrap_mini_cart_item_name()
   en functions.php) a ítems independientes, cada uno posicionable por
   separado. El link en sí sigue funcionando igual — un clic en la imagen o
   en el nombre sigue llevando al producto, `display:contents` no saca al
   <a> del DOM, solo de su propio render de caja. */
.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item a:not(.remove) {
	display: contents;
}

.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item a:not(.remove) img {
	/* Fuera del grid — ver el comentario de arriba sobre por qué (evita que
	   su alto de 96px infle las filas de nombre/precio). Ancla contra el
	   `<li>` (position:relative), en la esquina superior izquierda, igual
	   que antes visualmente.
	   ⚠️ `top` en 10px, no 0 — para un elemento `position:absolute`, el
	   `top:0` referencia el borde de la PADDING BOX del ancestro
	   posicionado (el `<li>`), que empieza en el mismo punto que su
	   border-box cuando no hay borde — ignora por completo el
	   `padding:10px 0` del `<li>`. Con `top:0` la imagen quedaba pegada al
	   límite exterior real de la fila, 10px más arriba que el nombre (que
	   sí respeta el padding, al seguir siendo un ítem normal del grid) —
	   bug real, encontrado verificando en vivo (`imgRect.top` vs
	   `nameRect.top`, ~10px de diferencia). `top:10px` iguala el padding. */
	position: absolute;
	top: 10px;
	left: 0;
	width: 96px; /* x2 sobre el original de 48px */
	height: 96px;
	/* ⚠️ Bug real, encontrado verificando en vivo — con solo `width`/`height`
	   la imagen quedaba angosta (~46px) y alta (96px), no cuadrada.
	   `.product_list_widget li img { max-width: 2.61792em }` (Storefront,
	   woocommerce.css) le gana a `width:96px` en el ancho REAL: `width` y
	   `max-width` son propiedades independientes en la cascada — esta regla
	   nunca tocaba `max-width`, así que la de Storefront seguía aplicando
	   encima sin ningún conflicto que la venciera, sin importar cuánta
	   especificidad tuviera el resto de este selector. `max-width:none`
	   la anula. */
	max-width: none;
	object-fit: cover;
	border: 1px solid rgba(244, 239, 231, 0.2);
}

.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item .djj-cart-item-name {
	min-width: 0;
	font-family: 'Cormorant Garamond', serif;
	font-size: 22px; /* 17px x1.3 */
	color: var(--djj-cream);
}

/* ⚠️ Escritorio — bug real, reportado por el usuario con capturas: con un
   nombre largo (2 líneas) el precio quedaba renderizado por debajo del
   borde inferior de la imagen. La letra del nombre en escritorio (22px) es
   25% más grande que en móvil (17.6px) — un nombre de 2 líneas ocupa más
   alto ahí (hasta ~71px medido en vivo con un nombre real), y la imagen
   sigue fija en 96px (no participa del grid, no puede "crecer sola" para
   acompañar al texto) — el contenido (nombre + separación + precio) supera
   los 96px disponibles y el precio se sale por abajo. En móvil no se nota
   porque la letra más chica mantiene el contenido dentro del alto de la
   imagen. Imagen agrandada en escritorio para que visualmente se vea
   contenida igual que en móvil — 120px (mismo +25% que la letra, 96 ×
   1.25), con margen real de sobra para 2 líneas + precio (10px arriba +
   71px nombre + 4px separación + 27.5px precio = 112.5px, cabe con margen
   dentro de 120px de imagen + 10px de arriba). */
@media (min-width: 768px) {
	.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item {
		padding-left: 130px; /* 120px imagen + 10px separación, mismo criterio que antes */
		min-height: 140px; /* 120px imagen + 10px arriba + 10px abajo, mismo criterio que antes */
	}

	.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item a:not(.remove) img {
		width: 120px;
		height: 120px;
	}
}

/* Móvil — espacio entre la imagen y el nombre del producto a 15px (antes
   10px, regla base de arriba — sin tocar acá, sigue siendo el valor real en
   escritorio) y la letra del nombre un 20% más chica (22px × 0.8 = 17.6px).
   El espacio imagen↔texto vive en el `padding-left` del `<li>` (ver
   arriba) — 96px imagen + 15px en vez de 10px. */
@media (max-width: 767px) {
	.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item {
		padding-left: 111px;
	}

	.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item .djj-cart-item-name {
		font-size: 17.6px; /* 22px - 20% */
	}
}

/* Debajo del nombre, alineado a su borde izquierdo sin margen a mano —
   misma columna de ancho completo (pedido explícito del usuario: "debajo
   del nombre, alineado del lado izquierdo con el nombre" — antes en su
   propia columna a la derecha, alineado con el borde inferior de la
   imagen). */
.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item .quantity {
	min-width: 0;
	font-family: 'Poppins', sans-serif;
	color: var(--djj-gold);
	font-size: 17px; /* 14px x1.2 */
	font-weight: 700;
	white-space: nowrap;
}

/* Línea 2: ÍCONO de caneca (papelera) en vez de texto — dos intentos con
   texto ("Eliminar" subrayado dorado, luego un chip con borde dorado y
   texto crema) se reportaron invisibles en más de un dispositivo real, con
   el color siempre confirmado correcto en toda prueba remota (ver README
   sección 12.2.1 para el historial completo: causa de `icons.css` de
   Storefront recortando el alto, y luego el fallo de pintado del color de
   texto en sí, nunca explicado del todo). En vez de seguir dependiendo de
   que un color de TEXTO pinte, se cambia de estrategia: un ícono via
   `mask-image` + `background-color`, la misma técnica ya probada y estable
   en producción para el ícono del carrito (7.10) y el del menú hamburguesa
   (7.4) — el color lo pone un `background-color` sobre una forma, no el
   pintado de glifos de una fuente. El texto "Eliminar" queda en el DOM
   (font-size:0, invisible pero seleccionable/accesible) — además el link
   ya trae su propio `aria-label` nativo de WooCommerce ("Eliminar
   {producto} del carrito"), así que la accesibilidad no depende de este
   texto visualmente oculto. Tamaño fijo en píxeles (no `fit-content` ni
   `auto`), para no repetir el colapso de ancho ya visto con esa
   propiedad. */
.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item a.remove {
	/* Movido a la esquina superior derecha de cada producto (antes fila
	   propia abajo, alineado a la izquierda). Ya no participa del grid
	   (position:absolute lo saca del flujo) — ancla contra el `li`
	   (position:relative, ver arriba), no contra el drawer entero. */
	position: absolute;
	top: 0;
	right: 0;
	box-sizing: border-box;
	width: 32.4px; /* -10% sobre el original de 36px, sin achicar el ícono (::before, sigue en 16px) */
	height: 32.4px;
	padding: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	border: none; /* marco dorado quitado a pedido del usuario */
	border-radius: 2px;
	background: transparent;
	font-size: 0;
	line-height: 0;
	color: transparent;
	overflow: visible;
	text-decoration: none;
	/* CAUSA RAÍZ real de que "Eliminar" nunca se viera, en NINGÚN color
	   probado (subrayado dorado, chip dorado, chip crema): icons.css de
	   Storefront trae `a.remove { text-indent: -9999px; ... }`, sin
	   calificador — empuja el texto 9999px fuera de pantalla, siempre.
	   Ninguna verificación anterior lo detectó porque `getComputedStyle`
	   seguía devolviendo el `color` "correcto" (la propiedad `color` no
	   tiene nada que ver con `text-indent`) y `getBoundingClientRect()` en
	   el link medía la caja/borde, no la posición real de los glifos. */
	text-indent: 0;
}

.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item a.remove::before {
	content: "";
	display: block;
	/* icons.css también trae `a.remove::before { position:absolute;
	   top:0;left:0;right:0;bottom:0; ... }` sin calificador — nunca
	   anulábamos `position` acá, así que el ícono se posicionaba absoluto
	   contra el ancestro posicionado más cercano (el drawer, `position:
	   fixed`), escapando a la esquina superior izquierda del drawer en vez
	   de quedar centrado dentro del botón de 36×36px. */
	position: static;
	width: 16px;
	height: 16px;
	/* Gris, misma opacidad (0.6) que ya usaba en dorado (mismo tono que las
	   líneas de separación entre productos, `rgba(201, 162, 93, ...)`, ver
	   `.woocommerce-mini-cart-item` más arriba). */
	background-color: rgba(153, 153, 153, 0.6);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 6h18'/%3E%3Cpath d='M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2'/%3E%3Cpath d='M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6'/%3E%3Cline x1='10' y1='11' x2='10' y2='17'/%3E%3Cline x1='14' y1='11' x2='14' y2='17'/%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='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 6h18'/%3E%3Cpath d='M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2'/%3E%3Cpath d='M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6'/%3E%3Cline x1='10' y1='11' x2='10' y2='17'/%3E%3Cline x1='14' y1='11' x2='14' y2='17'/%3E%3C/svg%3E") center / contain no-repeat;
}

.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item a.remove:hover {
	background: var(--djj-gold);
}

.djj-cart-drawer__body ul.woocommerce-mini-cart li.woocommerce-mini-cart-item a.remove:hover::before {
	background-color: var(--djj-dark);
}

.djj-cart-drawer__body p.woocommerce-mini-cart__total {
	display: flex;
	justify-content: space-between;
	align-items: center;
	color: rgba(244, 239, 231, 0.7);
	font-size: 14px;
	padding-top: 16px;
	margin: auto 0 16px; /* margin-top:auto = ancla el footer (total+botón) al fondo del drawer */
	border-top: 1px solid rgba(201, 162, 93, 0.25);
}

.djj-cart-drawer__body p.woocommerce-mini-cart__total .woocommerce-Price-amount {
	color: var(--djj-cream);
	font-size: 18px;
	font-weight: 600;
}

.djj-cart-drawer__body p.woocommerce-mini-cart__buttons {
	margin: 0;
}

.djj-cart-drawer__body p.woocommerce-mini-cart__buttons a.checkout {
	display: block;
	width: 100%;
	box-sizing: border-box;
	padding: 16px;
	background: var(--djj-gold);
	color: var(--djj-dark);
	border: none;
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	text-align: center;
	font-family: 'Poppins', sans-serif;
	font-weight: 600;
	text-decoration: none;
}

.djj-cart-drawer__body p.woocommerce-mini-cart__buttons a.checkout:hover {
	background: var(--djj-cream);
}

.djj-cart-drawer__body li.djj-mini-cart-add-more {
	list-style: none;
	padding: 0;
	margin-top: 12px;
}

.djj-mini-cart-add-more__link {
	display: block;
	width: 100%;
	box-sizing: border-box;
	padding: 14px;
	border: 1px dashed var(--djj-gold);
	text-align: center;
	font-family: 'Poppins', sans-serif;
	font-size: 13px;
	color: var(--djj-gold);
	text-decoration: none;
}

.djj-mini-cart-add-more__link:hover {
	background: rgba(201, 162, 93, 0.1);
}

.djj-mini-cart-add-more__link:hover {
	color: var(--djj-cream);
}

/* ==================== BOTÓN FLOTANTE DE WHATSAPP (sitewide) ==================== */

.djj-whatsapp-fab {
	position: fixed;
	right: 20px;
	bottom: 20px;
	width: 56px;
	height: 56px;
	background: #25D366;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
	/* Por encima del header fijo (99) y del drawer de carrito (100/101). */
	z-index: 200;
	transition: transform 0.2s ease, bottom 0.3s ease;
}

/* Con el drawer abierto, el botón quedaba encima de "Continuar al pago". Se sube
   justo por encima de la línea del total — offset fijo porque el bloque total+botón
   siempre mide lo mismo (está anclado al fondo del drawer, ver 12.2 en el README). */
body.djj-cart-open .djj-whatsapp-fab {
	bottom: 150px;
}

.djj-whatsapp-fab:hover {
	transform: scale(1.08);
}

.djj-whatsapp-fab svg {
	width: 30px;
	height: 30px;
	fill: #FFFFFF;
}

@media (max-width: 767px) {
	.djj-whatsapp-fab {
		width: 50px;
		height: 50px;
		right: 16px;
		bottom: 16px;
	}

	.djj-whatsapp-fab svg {
		width: 26px;
		height: 26px;
	}
}

/* ==================== CARRITO (cart.php, sin JS / acceso directo) ==================== */

.woocommerce-cart #primary {
	max-width: none;
	width: 100%;
	float: none;
}

.woocommerce-cart .woocommerce {
	padding: clamp(48px, 9vw, 100px) clamp(20px, 5vw, 48px);
	background: var(--djj-cream);
	box-sizing: border-box;
	max-width: 1100px;
	margin: 0 auto;
}

.woocommerce-cart table.shop_table {
	border: 1px solid rgba(14, 58, 67, 0.15);
	border-collapse: collapse;
	width: 100%;
}

.woocommerce-cart table.shop_table th {
	font-family: 'Poppins', sans-serif;
	font-size: 11px;
	letter-spacing: 1px;
	text-transform: uppercase;
	color: var(--djj-teal);
	border-bottom: 1px solid rgba(14, 58, 67, 0.15);
}

.woocommerce-cart table.shop_table td {
	border-bottom: 1px solid rgba(14, 58, 67, 0.1);
}

/* Miniatura de producto en la página completa del carrito (pedido original:
   sin imagen — el usuario pidió traerla de vuelta). Ancho fijo de columna +
   imagen cuadrada, mismo borde sutil que ya usa la galería de la ficha de
   producto (10.16, .woocommerce-product-gallery img). */
.woocommerce-cart table.shop_table .product-thumbnail {
	width: 72px;
}

.woocommerce-cart table.shop_table .product-thumbnail img {
	width: 64px;
	/* Storefront trae `.product-thumbnail img { max-width: 3.7em }` propio
	   (woocommerce.css) — sin este override, esa cota (~59px) le gana al
	   `width` de acá: `max-width` siempre limita a `width`, sin importar
	   cuál de las dos reglas "gana" la cascada, porque son declaraciones de
	   propiedades DISTINTAS (cada una se resuelve por su cuenta). */
	max-width: none;
	height: 64px;
	object-fit: cover;
	border: 1px solid rgba(14, 58, 67, 0.12);
	display: block;
}

/* El link "Eliminar" ya trae el texto correcto (filtro djjoyeros_mini_cart_remove_link_text,
   compartido con el drawer), pero WooCommerce lo estiliza por defecto como un botón
   circular de ~26×26px pensado para un solo carácter "×" — con la palabra "Eliminar"
   adentro se veía cortado/roto. Se restylea como link de texto, y se angosta la columna
   completa (que traía ancho de sobra reservado para ese botón), lo que además le da
   más espacio a la columna del nombre del producto y la corre a la izquierda. */
.woocommerce-cart table.shop_table .product-remove {
	width: 80px;
	/* WooCommerce trae ~25.9px de padding por lado en esta celda por defecto —
	   con la columna angosta y ese padding intacto, no queda espacio de sobra
	   para el texto "Eliminar" y el link terminaba colapsando a 0 de ancho. */
	padding: 16px 8px !important;
	text-align: left;
}

.woocommerce-cart table.shop_table .remove {
	/* OJO: display:inline-block aquí colapsa el link a 0 de ancho (bug real,
	   confirmado aislando propiedad por propiedad vía CSSOM) — display:block
	   (el valor nativo de WooCommerce, dejado tal cual) sí funciona. */
	width: auto !important;
	height: auto !important;
	overflow: visible !important; /* mismo icons.css `a.remove{overflow:hidden}` del drawer (ver más abajo) — acá ya no debería recortar nada con height:auto, pero se anula también por las dudas */
	display: block !important;
	float: none !important;
	background: none !important;
	border-radius: 0 !important;
	color: var(--djj-gold) !important;
	font-size: 12px !important;
	line-height: normal !important;
	text-decoration: underline !important;
	padding: 0 !important;
}

.woocommerce-cart table.shop_table .remove:hover {
	background: none;
	color: var(--djj-teal);
}

/* Mismo ícono de Font Awesome en ::before, posicionado absoluto sobre todo el
   link, tapando el texto "Eliminar" — ver la misma nota en la sección del drawer. */
.woocommerce-cart table.shop_table .remove::before {
	content: none !important;
	display: none !important;
}

.woocommerce-cart .product-name a {
	font-family: 'Cormorant Garamond', serif;
	font-size: 17px;
	color: var(--djj-dark);
}

.woocommerce-cart .cart_totals h2 {
	font-family: 'Cormorant Garamond', serif;
	font-weight: 500;
	color: var(--djj-dark);
}

.woocommerce-cart .wc-proceed-to-checkout .checkout-button {
	background: var(--djj-dark) !important;
	color: var(--djj-cream) !important;
	border: none;
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	border-radius: 0;
	font-family: 'Poppins', sans-serif;
}

.woocommerce-cart .wc-proceed-to-checkout .checkout-button:hover {
	background: var(--djj-teal) !important;
}

.woocommerce-cart input.qty {
	border: 1px solid rgba(14, 58, 67, 0.2);
	font-family: 'Poppins', sans-serif;
}

.woocommerce-cart .coupon .button {
	border-radius: 0;
}

/* ====================================================================
   CHECKOUT — panel angosto anclado a la derecha (mockup del usuario)
   ====================================================================
   Sigue siendo la página real /pedido/ (navegación normal, sin overlay por
   JS — decisión explícita del usuario para no arriesgar el flujo de pago
   con una arquitectura más compleja, justo después de que desactivar
   Elementor rompiera el checkout esta misma sesión), pero con apariencia
   de panel: fondo oscuro detrás, tarjeta angosta anclada a la derecha,
   alto completo de pantalla, con su propio encabezado ("Finalizar pago" +
   cerrar + volver al carrito) en vez del header/título nativos del sitio.
   Ver README §13.1.3 para el detalle completo de esta sección. */

body.woocommerce-checkout #masthead,
body.woocommerce-checkout #colophon,
body.woocommerce-checkout .djj-whatsapp-fab {
	display: none;
}

body.woocommerce-checkout {
	padding-top: 0; /* sin header fijo que compensar — el panel trae el suyo */
	background: var(--djj-dark);
}

body.woocommerce-checkout #primary,
body.woocommerce-checkout .content-area {
	max-width: none;
	width: 100%;
	float: none;
	margin: 0;
	padding: 0;
}

/* Oculta el título nativo de la página ("Pedido") — el panel trae su propio
   título "Finalizar pago" (inyectado por PHP, ver djjoyeros_checkout_panel_header). */
body.woocommerce-checkout .entry-header {
	display: none;
}

/* `position:fixed`, no ancho relativo dentro del flujo normal — el checkout
   (página 28) resultó estar armado con Elementor por debajo (ver README
   §18, el mismo hallazgo de cuando desactivar el plugin lo rompió), con
   varios contenedores de Elementor anidados que traen su propio max-width
   (`.col-full`, `.e-con-inner`, etc.) y pelean con cualquier intento de
   anclar el panel al viewport real usando `margin-left:auto` dentro del
   flujo normal — quedaba angosto y centrado en el medio de esos
   contenedores en vez de pegado al borde derecho de la pantalla. `fixed`
   escapa por completo de esa cadena de ancestros, igual que ya hace el
   drawer del carrito (`.djj-cart-drawer`, sección 12.2). */
body.woocommerce-checkout .woocommerce {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	width: 460px;
	max-width: 100vw;
	background: var(--djj-teal);
	padding: 0;
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	box-shadow: -20px 0 60px rgba(10, 26, 34, 0.4);
	z-index: 10;
}

.djj-checkout-panel__header {
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 24px 28px 20px;
	border-bottom: 1px solid rgba(201, 162, 93, 0.25);
}

.djj-checkout-panel__title {
	font-family: 'Cormorant Garamond', serif;
	font-size: 20.8px; /* -20% a pedido explícito del usuario — 26px × 0.8 */
	color: var(--djj-cream);
}

/* `text-decoration: none !important` en los dos — Storefront trae
   `.hentry .entry-content a { text-decoration: underline; }` (2 clases,
   más específico que estos selectores de 1 clase) que se aplica también
   acá porque el panel entero vive dentro de `.entry-content` (el
   contenedor nativo del contenido de la página "Pedido"). */
.djj-checkout-panel__close {
	background: none;
	border: none;
	color: var(--djj-gold);
	font-size: 22px;
	line-height: 1;
	text-decoration: none !important;
	cursor: pointer;
}

.djj-checkout-panel__back {
	flex-shrink: 0;
	display: block;
	padding: 16px 28px 0;
	font-family: 'Poppins', sans-serif;
	font-size: 13px;
	color: var(--djj-gold);
	text-decoration: none !important;
}

.djj-checkout-panel__back:hover {
	color: var(--djj-cream);
}

/* ⚠️ El form entero hacía scroll como una sola pieza (incluido el pie) —
   eso es justo lo que causó el bug real de las capturas (ver el comentario
   completo en `.djj-checkout-panel__footer`, más abajo): con TODO adentro
   del mismo scroll, no hay forma de que el pie quede realmente fijo sin
   taparse con el contenido real al hacer scroll. Ahora el form es solo el
   contenedor EXTERIOR (flex column, ya NO scrollea él mismo) — el scroll
   de verdad vive en `.djj-checkout-panel__scroll` (el wrapper nuevo que
   envuelve campos + resumen, ver functions.php), dejando el pie como
   hermano de ese wrapper, totalmente afuera del área que se desplaza. */
/* `margin-bottom` nativo de Storefront (`1.618em`, ~25.9px) en todo `<form>`
   — invisible en `getBoundingClientRect()` (no participa del border-box),
   pero sí sumaba al espacio real bajo el pie del panel junto con el
   `padding-bottom` propio de acá. Confirmado con `getComputedStyle`, mismo
   patrón ya documentado para `.site-branding` (README, notas del proyecto). */
body.woocommerce-checkout form.checkout {
	flex: 1;
	min-height: 0;
	display: flex;
	flex-direction: column;
	margin-bottom: 0;
	padding: 20px 28px 20px;
	box-sizing: border-box;
}

body.woocommerce-checkout .djj-checkout-panel__scroll {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
}

/* Fondo blanco encontrado en un <style> inline (no de este archivo, probablemente
   de WooCommerce Blocks o del kit de Elementor) — sin esto, "Entrega" y "Método
   de pago" se veían blancas en vez del mismo teal del resto del panel. Hace
   falta !important: un <style> inline pesa igual que un archivo externo en la
   cascada (no gana solo por estar inline), pero tampoco pierde contra una regla
   externa sin !important de la misma especificidad — sí pierde contra !important. */
body.woocommerce-checkout #order_review {
	background: transparent !important;
}

.djj-checkout-panel__eyebrow {
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	color: var(--djj-gold);
	margin: 28px 0 14px;
}

.djj-checkout-panel__eyebrow:first-child {
	margin-top: 0;
}

/* Oculta los títulos nativos que reemplazan los eyebrows de arriba */
body.woocommerce-checkout .woocommerce-billing-fields > h3,
body.woocommerce-checkout .woocommerce-shipping-fields > h3,
body.woocommerce-checkout #order_review_heading {
	display: none;
}

/* "¿Enviar a una dirección diferente?" — el diseño no lo contempla, siempre
   se envía a la dirección de facturación. */
body.woocommerce-checkout .woocommerce-shipping-fields {
	display: none;
}

/* El campo de cupón no aparece en el mockup. */
body.woocommerce-checkout .woocommerce-form-coupon-toggle,
body.woocommerce-checkout .checkout_coupon {
	display: none;
}

/* Campos de formulario — todos full-width salvo Tipo/Número de documento
   (form-row-first/form-row-last nativos, ya en 2 columnas). */
body.woocommerce-checkout .form-row {
	margin: 0 0 12px;
	padding: 0;
	width: 100%;
	box-sizing: border-box;
}

/* El mockup no muestra labels — el placeholder hace de label visual. Las
   labels siguen en el DOM (accesibilidad, lectores de pantalla), solo se
   ocultan visualmente con el mismo patrón sr-only ya usado en el header. */
body.woocommerce-checkout label {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	margin: -1px;
	white-space: nowrap;
	border: 0;
	padding: 0;
}

body.woocommerce-checkout .form-row input.input-text,
body.woocommerce-checkout .form-row textarea,
body.woocommerce-checkout .form-row select {
	display: block;
	width: 100%;
	box-sizing: border-box;
	padding: 14px 16px;
	background: var(--djj-dark);
	border: 1px solid rgba(201, 162, 93, 0.2);
	color: var(--djj-cream);
	font-family: 'Poppins', sans-serif;
	font-size: 14px;
	border-radius: 0;
}

body.woocommerce-checkout .form-row input.input-text::placeholder,
body.woocommerce-checkout .form-row textarea::placeholder {
	color: rgba(244, 239, 231, 0.45);
}

body.woocommerce-checkout .form-row input.input-text:focus,
body.woocommerce-checkout .form-row textarea:focus,
body.woocommerce-checkout .form-row select:focus {
	border-color: var(--djj-gold);
}

/* Flechita propia en los selects nativos (mismo mecanismo mask-image que el
   resto de los íconos del sitio no aplica acá — es más simple usar la forma
   como imagen de fondo directamente, no hay recoloreo dinámico que necesite
   `background-color`+máscara). */
body.woocommerce-checkout .form-row select {
	appearance: none;
	-webkit-appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23C9A25D' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 14px center;
	background-size: 16px;
	padding-right: 40px;
}

/* Ciudad ya elegida: texto en blanco y con más peso, distinto del resto de
   los campos vacíos (mismo criterio visual del mockup, que la muestra
   distinta al resto de los placeholders). */
body.woocommerce-checkout #billing_city {
	font-weight: 600;
	color: var(--djj-cream);
}

body.woocommerce-checkout .select2-container--default .select2-selection--single {
	background: var(--djj-dark);
	border: 1px solid rgba(201, 162, 93, 0.2);
	height: 48px;
	border-radius: 0;
}

body.woocommerce-checkout .select2-container--default .select2-selection--single .select2-selection__rendered {
	color: var(--djj-cream);
	line-height: 46px;
	padding-left: 16px;
}

/* Documento: Tipo (CC/CE/NIT/Pasaporte) + Número, en una sola fila de 2
   columnas — ya traen form-row-first/form-row-last nativos de WooCommerce. */
body.woocommerce-checkout .form-row-first,
body.woocommerce-checkout .form-row-last {
	width: calc(50% - 6px);
	float: left;
	box-sizing: border-box;
}

body.woocommerce-checkout .form-row-first {
	margin-right: 12px;
}

/**
 * Tipo de documento (form-row-first) reducido — primero al 80% de su ancho
 * original, y en una vuelta posterior otro 5% más (0.8 × 0.95 = 0.76) — con
 * Número de documento (form-row-last) creciendo lo que Tipo cedió, para que
 * el borde derecho de Número quede alineado con el resto de los campos de
 * texto (`form-row-wide`, 100% del contenedor). El ancho de Tipo se guarda
 * en una custom property en el contenedor que ambos comparten
 * (`.woocommerce-billing-fields__field-wrapper`, su padre real en el DOM)
 * para no repetir la fórmula dos veces y que ambos anchos queden siempre
 * consistentes entre sí, se ajuste lo que se ajuste en el futuro.
 */
body.woocommerce-checkout .woocommerce-billing-fields__field-wrapper {
	--djj-doctype-width: calc((50% - 6px) * 0.76);
}

body.woocommerce-checkout #billing_document_type_field {
	width: var(--djj-doctype-width);
}

body.woocommerce-checkout #billing_document_number_field {
	width: calc(100% - var(--djj-doctype-width) - 12px);
}

body.woocommerce-checkout .form-row-first::after,
body.woocommerce-checkout .form-row-last::after {
	content: '';
	display: table;
	clear: both;
}

/* Campos que WooCommerce sigue necesitando (Apellidos, País, Departamento)
   pero el mockup no muestra — siguen funcionales (Apellidos vacío a
   propósito, ver README §13.1.3; País siempre Colombia; Departamento se
   deriva de la Ciudad vía JS), solo ocultos visualmente. */
body.woocommerce-checkout .djj-checkout-hidden-field {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	margin: -1px;
	white-space: nowrap;
	border: 0;
	padding: 0;
}

/* Tabla de resumen del pedido: se oculta la lista de productos y el
   subtotal (decisión del usuario — el repaso de productos queda para una
   pantalla de confirmación futura, no esta), y también la fila del total
   nativa (se reconstruye en el pie fijo del panel, ver más abajo) — se
   mantiene únicamente la fila de envío, restyleada como sección "Entrega". */
body.woocommerce-checkout table.woocommerce-checkout-review-order-table thead,
body.woocommerce-checkout table.woocommerce-checkout-review-order-table tbody,
body.woocommerce-checkout table.woocommerce-checkout-review-order-table tr.cart-subtotal,
body.woocommerce-checkout table.woocommerce-checkout-review-order-table tr.order-total {
	display: none;
}

body.woocommerce-checkout table.woocommerce-checkout-review-order-table,
body.woocommerce-checkout table.woocommerce-checkout-review-order-table tfoot,
body.woocommerce-checkout table.woocommerce-checkout-review-order-table tr.shipping {
	display: block;
	width: 100%;
	border: none;
}

body.woocommerce-checkout table.woocommerce-checkout-review-order-table tr.shipping th {
	display: none;
}

body.woocommerce-checkout table.woocommerce-checkout-review-order-table tr.shipping td {
	display: block;
	padding: 0;
}

/* Fila propia para el eyebrow "Entrega" (tr.djj-checkout-panel__eyebrow-row,
   ver djjoyeros_checkout_section_eyebrow_entrega en functions.php) — tiene
   que ser una fila de tabla válida, no un <div> suelto (ver el comentario
   en PHP sobre por qué), así que necesita el mismo display:block que el
   resto de las filas de esta tabla convertida a layout de bloque. */
body.woocommerce-checkout table.woocommerce-checkout-review-order-table tr.djj-checkout-panel__eyebrow-row,
body.woocommerce-checkout table.woocommerce-checkout-review-order-table tr.djj-checkout-panel__eyebrow-row td {
	display: block;
	padding: 0;
	border: none;
}

/* "Método de envío" (ver djjoyeros_checkout_section_metodo_envio en
   functions.php) — vive DENTRO de la tabla, en su propia fila
   tr.djj-checkout-panel__eyebrow-row (mismo truco que "Entrega", ver
   arriba). Esta regla solo pone la tipografía del párrafo en sí. */
.djj-checkout-panel__shipping-method {
	margin: 0 0 4px;
	font-family: 'Poppins', sans-serif;
	font-size: 14px;
	color: var(--djj-cream);
}

/* Tarjetas de método de envío (Entrega en persona / Dejar en portería) y de
   método de pago (gateways reales — hoy solo COD, ePayco pendiente de
   credenciales) — `.djj-selected` la pone JS al elegir un radio
   (checkout-rules.js), no `:has()` — más robusto en un flujo tan crítico
   como el pago. */
body.woocommerce-checkout ul#shipping_method,
body.woocommerce-checkout ul.payment_methods {
	list-style: none;
	margin: 0 0 4px;
	padding: 0;
	border: none !important;
}

/* 10px de espacio vacío debajo de la tarjeta real de pago (COD) — a
   propósito `padding-bottom`, no `margin-bottom`: el margin-bottom del
   último `<li>` (10px, la separación normal entre tarjetas) colapsa con
   cualquier margin-bottom que se le ponga a este `<ul>` (no hay padding ni
   borde entre ambos que lo evite) y el resultado sería el mayor de los dos,
   no la suma — con padding no hay colapso, así que se suma de verdad.
   ⚠️ `#payment .payment_methods { padding:0 !important }` de
   `woocommerce.css` también usa `!important` — en un empate de
   `!important`, decide la especificidad, y su `#payment` (ID) le gana a
   cualquier cantidad de clases. Hace falta igualar con `#payment` acá. */
body.woocommerce-checkout #payment ul.payment_methods {
	padding-bottom: 10px !important;
}

/**
 * ⚠️ Bug real, reportado con una captura — "Pago contra entrega" se veía con
 * fondo blanco/gris y prácticamente sin contraste (texto claro sobre claro),
 * distinto a las demás tarjetas: un `<style>` inline ajeno al tema (no de
 * este archivo — mismo patrón ya documentado para `#order_review`, 13.1.3a)
 * trae `#payment .payment_methods > li:not(.woocommerce-notice) {
 * background-color:#f5f5f5 }`, con un selector con ID (`#payment`) que le
 * gana en especificidad a este de acá, una clase nada más. Hace falta
 * `!important` para ganarle, tanto en el estado normal como en `.djj-selected`.
 */
body.woocommerce-checkout ul#shipping_method li,
body.woocommerce-checkout ul.payment_methods li.wc_payment_method {
	position: relative;
	list-style: none;
	margin-bottom: 10px;
	/* !important en el padding-bottom: Storefront trae
	   `#payment .payment_methods li:last-child { padding-bottom: 0 }`, con
	   ID — gana el empate contra esta regla si el gateway real (COD) queda
	   como único método visible (único hijo = también :last-child),
	   dejando esa tarjeta más baja que las demás. */
	padding: 14px 16px !important;
	/* !important también en el borde completo: la MISMA regla de arriba
	   (`li:last-child`) también trae `border-bottom: 0` — sin la tarjeta de
	   pago faltaba justo la línea inferior, mientras el resto del borde
	   (arriba/izq/der) sí se veía bien. Reportado con captura real. */
	border: 1px solid rgba(201, 162, 93, 0.25) !important;
	background: transparent !important;
	display: flex;
	align-items: center;
}

body.woocommerce-checkout ul#shipping_method li.djj-selected,
body.woocommerce-checkout ul.payment_methods li.djj-selected {
	border-color: var(--djj-gold);
	background: rgba(201, 162, 93, 0.08) !important;
}

/**
 * ⚠️ Bug real, mismo reporte — el círculo "seleccionado" que aparecía junto
 * a "Pago contra entrega" era MORADO, no dorado: no es el `<input
 * type="radio">` real (que si se ve, ya sale dorado por `accent-color` más
 * abajo) sino un ícono decorativo PROPIO de Storefront, dibujado con
 * Font Awesome vía `label::before` (`icons.css`, con selector `#payment
 * .payment_methods > li > label::before`) y coloreado por el mismo
 * `<style>` inline de arriba (`color: rgb(127, 84, 179)`, el morado por
 * defecto del customizer de Storefront — nunca personalizado a la marca).
 * Es un mecanismo de Storefront completamente aparte de nuestra tarjeta
 * dorada (`.djj-selected`), que además WooCommerce reemplaza por este
 * ícono automáticamente cuando solo hay UN método de pago disponible
 * (oculta el `<input>` real por JS propio — `checkout.js`,
 * `init_payment_methods()` — y este ícono queda como único indicador
 * visual). Se oculta por completo: el borde/fondo dorado de `.djj-selected`
 * ya comunica "seleccionado" por sí solo, igual que en las 3 tarjetas "de
 * vidriera" (que usan su propio círculo, `.djj-payment-preview__radio`, no
 * este).
 */
body.woocommerce-checkout ul.payment_methods li.wc_payment_method > label::before {
	display: none !important;
	content: none !important;
}

/**
 * ⚠️ 4 rondas de bugs reales, cada una encontrada recién al ver el sitio en
 * un dispositivo real (el navegador de pruebas nunca los reprodujo):
 * WooCommerce oculta el `<input>` real cuando hay un solo método de pago
 * disponible (`checkout.js`); `icons.css` de Storefront, por su cuenta,
 * también lo encoge a 1x1px, lo posiciona absoluto y le aplica el patrón
 * "solo para lectores de pantalla" (`clip-path`/`clip`/`overflow`); y el
 * `<label>` se queda con ~20px de padding de sobra, pensado para el ícono
 * de Storefront que reemplazaba al radio (ya oculto más arriba). Se fueron
 * corrigiendo una por una, `!important` por `!important` — pero en un
 * dispositivo real el círculo, ya "visible" en el sentido estricto, seguía
 * saliendo más chico, pegado al texto (sin el margen) y de un color que no
 * coincidía con el resto — la representación NATIVA del radio del sistema
 * operativo (`accent-color` no se comporta idéntico en todos los
 * navegadores/Android) es, en el fondo, un control que no se puede
 * controlar por completo vía CSS mientras siga siendo nativo.
 *
 * Solución definitiva: dejar de pelear contra el radio nativo y dibujar el
 * círculo nosotros mismos con `appearance:none` — el mismo criterio que ya
 * usan las 3 tarjetas "de vidriera" (`.djj-payment-preview__radio`, un
 * `<span>` decorativo, nunca un `<input>` real). Con `appearance:none` el
 * navegador dejar de dibujar SU representación nativa por completo y el
 * radio pasa a ser una caja común y corriente, con el mismo control total
 * de tamaño/color/posición que cualquier otro elemento — sin depender de
 * qué tan bien cada navegador/SO implemente `accent-color`.
 */
body.woocommerce-checkout ul#shipping_method input[type="radio"],
body.woocommerce-checkout ul.payment_methods input[type="radio"] {
	display: inline-block !important;
	appearance: none !important;
	-webkit-appearance: none !important;
	width: 16px !important;
	height: 16px !important;
	position: relative !important;
	clip-path: none !important;
	clip: auto !important;
	overflow: visible !important;
	box-sizing: border-box;
	border-radius: 50%;
	/* !important: `icons.css` de Storefront trae `border:0` con el mismo
	   selector de ID de arriba — sin `!important` de ningún lado, gana la
	   especificidad (ID > clases), dejando el círculo sin borde visible. */
	border: 1px solid var(--djj-gold) !important;
	background: transparent;
	margin: 0 10px 0 0 !important;
	padding: 0;
	flex-shrink: 0;
	cursor: pointer;
}

/* !important preventivo en el punto dorado también: dado el patrón repetido
   de este bug puntual (5 rondas seguidas de reglas de Storefront con ID
   ganándole a esta misma zona), más vale curarse en salud acá también. */
body.woocommerce-checkout ul#shipping_method input[type="radio"]:checked::after,
body.woocommerce-checkout ul.payment_methods input[type="radio"]:checked::after {
	content: "";
	position: absolute;
	top: 3px;
	left: 3px;
	right: 3px;
	bottom: 3px;
	border-radius: 50%;
	background: var(--djj-gold) !important;
}

body.woocommerce-checkout ul#shipping_method label,
body.woocommerce-checkout ul.payment_methods label {
	position: static; /* pisa el sr-only general de labels, acá sí son visibles */
	display: inline;
	width: auto;
	height: auto;
	overflow: visible;
	clip: auto;
	margin: 0;
	padding: 0 !important;
	white-space: normal;
	color: var(--djj-cream);
	font-family: 'Poppins', sans-serif;
	font-size: 14px;
	font-weight: 600;
}

/* Detalle del gateway (ej. instrucciones de "Pago contra entrega") — no
   aplica al look de tarjeta simple del mockup, se oculta. */
body.woocommerce-checkout .payment_box {
	display: none !important;
}

/* Pie fijo del panel: Total + casilla de autorización + botón "Continuar
   con el pago", siempre visible sin importar cuánto scrollee el contenido
   de arriba. Vive fuera de las zonas que WooCommerce reemplaza por AJAX
   (la tabla de resumen y #payment) para no desaparecer en cada recálculo
   — checkout-rules.js mantiene el monto y el botón real sincronizados acá.
   ⚠️ Dos intentos fallidos antes de este, ambos reportados por el usuario
   con capturas reales — documentados acá para no repetirlos:
   1. `margin-top:auto` dentro de un flex column con `overflow-y:auto`
      (`form.checkout` completo) — solo "pinea" al fondo mientras el
      contenido de los hermanos NO desborda esa caja. Apenas el formulario
      creció (con la casilla de autorización, entre otras cosas) más allá
      del alto visible, el pie quedó al final de TODO el desborde, ~500px
      fuera de la vista, sin ninguna pista de que hacía falta scroll.
   2. `position:sticky; bottom:0` (mismo contenedor) — resolvió que apareciera,
      pero sticky pega el pie al fondo del MISMO scroll que los campos de
      dirección: mientras el usuario todavía escribía Ciudad/Dirección, el
      pie ya se veía pegado abajo tapando lo que seguía (Entrega/Método de
      pago), y al terminar de hacer scroll asomaba ese contenido real por
      detrás — exactamente lo que mostraban las capturas.
   Solución real: el pie ya NO comparte contenedor con scroll con los
   campos — es hermano de `.djj-checkout-panel__scroll` (el wrapper nuevo,
   ver functions.php), así que un simple `flex-shrink:0` alcanza: el
   `flex:1` del wrapper de scroll ya empuja el pie al fondo del panel por
   su cuenta, sin `margin-top:auto` ni `sticky` ni fondo propio — el pie
   sencillamente nunca fue parte de lo que se desplaza. */
.djj-checkout-panel__footer {
	flex-shrink: 0;
	padding-top: 20px;
	border-top: 1px solid rgba(201, 162, 93, 0.25);
}

.djj-checkout-panel__total {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 14px;
	color: rgba(244, 239, 231, 0.7);
	font-size: 14px;
	font-family: 'Poppins', sans-serif;
}

.djj-checkout-panel__total-amount {
	color: var(--djj-cream);
	font-size: 20px;
	font-weight: 600;
}

body.woocommerce-checkout .form-row.place-order {
	margin: 0;
	padding: 0;
}

body.woocommerce-checkout #place_order {
	display: block;
	width: 100%;
	box-sizing: border-box;
	padding: 16px;
	background: var(--djj-gold) !important;
	color: var(--djj-dark) !important;
	border: none;
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	font-weight: 600;
	border-radius: 0;
	font-family: 'Poppins', sans-serif;
	cursor: pointer;
}

body.woocommerce-checkout #place_order:hover {
	background: var(--djj-cream) !important;
}

/* ==================== "Pagar por el pedido" tras un rechazo de Wompi (13.4b) ====================
   Pedido explícito del usuario: que se vea igual que la página de
   confirmación (13.4) — título "Detalles del pedido" dorado y tabla
   blanca con margen lateral, en vez de la tabla nativa de
   `checkout/form-pay.php` (sin título, pegada a los bordes, con un fondo
   mixto: blanco en los `<th>` pero TRANSPARENTE en los `<td>` de las filas
   de totales — confirmado con `getComputedStyle` en vivo, se veía la mitad
   de cada fila con el panel oscuro asomando detrás). 16px de margen
   lateral — no los 28px de la página de confirmación (un contexto
   distinto) — para alinear con el padding que YA usa el resto de este
   panel más abajo (`#payment .form-row`, ver checkboxes/botón). */
/* ⚠️ Bug real, reportado por el usuario — sin scroll en esta pantalla, mismo
   patrón ya conocido del checkout (13.1.3) y de la confirmación (13.4): el
   panel fijo del checkout (`.woocommerce`, `position:fixed; height:720px`)
   viene con `overflow-y:visible` por defecto — cualquier contenido más alto
   que el panel queda genuinamente fuera de alcance, no solo oculto. En el
   checkout principal esto se resuelve con un wrapper propio
   (`.djj-checkout-panel__scroll`, ver `djjoyeros_checkout_scroll_open()`),
   pero ese wrapper se abre/cierra en hooks (`woocommerce_checkout_before_
   customer_details`/`_after_order_review`) exclusivos de `form-checkout.php`
   — nunca se ejecutan en `checkout/form-pay.php` (otra plantilla), así que
   esta pantalla se quedó sin ningún mecanismo de scroll. Acá no hace falta
   el wrapper (no tiene un pie fijo tipo sticky que separar) — alcanza con
   el mismo `overflow-y:auto` directo que ya usa la confirmación
   (`body.woocommerce-order-received .woocommerce-order`, sección 13.4).
   Selector con hijo directo (`.elementor-shortcode > .woocommerce`), no
   `.woocommerce` a secas — esa clase también la trae, sin relación, el
   widget de búsqueda del header (`.widget.woocommerce.widget_product_
   search`), confirmado con `querySelectorAll` en vivo. */
body.woocommerce-order-pay .elementor-shortcode > .woocommerce {
	overflow-y: auto;
}

body.woocommerce-order-pay .woocommerce-order-details__title {
	font-family: 'Cormorant Garamond', serif;
	color: var(--djj-gold);
	margin: 24px 16px 12px;
}

body.woocommerce-order-pay table.shop_table {
	margin: 0 16px 24px;
	width: calc(100% - 32px);
}

body.woocommerce-order-pay table.shop_table th,
body.woocommerce-order-pay table.shop_table td {
	background: #fdfdfd;
	color: #000000;
}

/* Botón "Cancelar" (djjoyeros_wompi_failed_order_cancel_button) — mismo
   tamaño/tipografía que "Reintentar pago" (#place_order, arriba), pero sin
   relleno: fondo del propio panel, solo el marco y el texto en dorado —
   pedido explícito del usuario, para diferenciarlo como la acción
   secundaria. */
.djj-order-pay-cancel {
	display: block;
	width: 100%;
	box-sizing: border-box;
	padding: 16px;
	margin-top: 10px;
	background: transparent;
	color: var(--djj-gold);
	border: 1px solid var(--djj-gold);
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	font-weight: 600;
	font-family: 'Poppins', sans-serif;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
}

.djj-order-pay-cancel:hover {
	background: rgba(201, 162, 93, 0.1);
}

/* Botón "Volver al inicio" (djjoyeros_thankyou_cancelled_home_button) —
   única acción de la pantalla de confirmación cuando el pedido quedó
   cancelado. Mismo tamaño/tipografía que el resto de los botones del
   panel, pero con relleno dorado (acción primaria, no secundaria como
   "Cancelar" arriba). Selector con `body.woocommerce-order-received` por
   especificidad — sin ese prefijo, `body.woocommerce-order-received a`
   (color dorado genérico para cualquier link de esta página, más arriba)
   le gana al `color` de acá (texto oscuro sobre fondo dorado) pese a venir
   después en el archivo — confirmado con `getComputedStyle`, texto
   ilegible (dorado sobre dorado) antes de este ajuste. */
body.woocommerce-order-received .djj-thankyou__home-button {
	display: block;
	width: 100%;
	box-sizing: border-box;
	padding: 16px;
	margin-top: 20px;
	background: var(--djj-gold);
	color: var(--djj-dark);
	border: none;
	font-size: 12px;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	font-weight: 600;
	font-family: 'Poppins', sans-serif;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
}

.djj-thankyou__home-button:hover {
	background: var(--djj-cream);
}

body.woocommerce-checkout .woocommerce-terms-and-conditions-wrapper,
body.woocommerce-checkout .woocommerce-privacy-policy-text,
body.woocommerce-checkout .djj-checkout-tyc {
	font-size: 11px;
	line-height: 1.5;
	color: rgba(244, 239, 231, 0.5);
	margin-bottom: 10px;
}

body.woocommerce-checkout .woocommerce-privacy-policy-text a {
	color: var(--djj-gold);
}

/* Casilla de autorización de tratamiento de datos (functions.php,
   djjoyeros_privacy_consent_required_message y ver el bloque de
   "Autorización de tratamiento de datos personales" más arriba en ese
   archivo) — mismo link dorado que ya usaba el aviso pasivo que
   reemplaza, ahora en el contexto real de la casilla nativa de
   WooCommerce (`.woocommerce-terms-and-conditions-checkbox-text`, no
   `.woocommerce-privacy-policy-text` — es un bloque distinto). El
   `<label>`/checkbox en sí hereda el tamaño/color ya definidos arriba
   para `.woocommerce-terms-and-conditions-wrapper`. */
body.woocommerce-checkout .woocommerce-terms-and-conditions-checkbox-text a {
	color: var(--djj-gold);
}

/* ⚠️ Bug real — la casilla nunca se veía porque este `<label>` sigue siendo
   un `label` genérico, y cae bajo la regla sr-only de arriba
   (`body.woocommerce-checkout label`, pensada solo para los labels de campo
   de texto que el placeholder reemplaza visualmente) — `position:absolute;
   width/height:1px; clip:rect(0,0,0,0)` lo dejaba sin tamaño ni visibilidad,
   igual que le pasó antes a los labels de `ul#shipping_method`/
   `ul.payment_methods` (mismo archivo, más abajo) — mismo patch, mismo
   motivo: pisar el sr-only explícitamente para los labels que sí deben
   verse. */
body.woocommerce-checkout .woocommerce-form__label-for-checkbox {
	position: static;
	width: auto;
	height: auto;
	overflow: visible;
	clip: auto;
	margin: 0;
	white-space: normal;
	display: flex;
	align-items: flex-start;
	gap: 8px;
	cursor: pointer;
}

body.woocommerce-checkout #terms,
body.woocommerce-checkout #djj_tyc_accept {
	margin-top: 2px;
	flex-shrink: 0;
	accent-color: var(--djj-gold);
}

/* Segunda casilla (Términos y Condiciones, djjoyeros_checkout_terms_checkbox,
   functions.php) — mismo espaciado vertical entre las dos filas de checkbox
   que ya usa `.form-row` en el resto del checkout, para que no queden
   pegadas entre sí ni contra la casilla de privacidad de arriba. */
body.woocommerce-checkout .djj-checkout-tyc {
	margin-top: 12px;
}

/* Asterisco "*" nativo de WooCommerce para campo obligatorio, a la derecha
   del texto — a pedido del usuario, no debe verse (junto con el subrayado
   punteado que el navegador pone por defecto en cualquier `abbr[title]`,
   que se leía como "tres puntos" pegados al asterisco). Cubre las dos
   casillas: la de privacidad (dentro de `.woocommerce-terms-and-conditions-wrapper`)
   y la de Términos y Condiciones (`.djj-checkout-tyc`, fuera de ese wrapper
   — mismo criterio visual, misma regla extendida). */
body.woocommerce-checkout .woocommerce-terms-and-conditions-wrapper abbr.required,
body.woocommerce-checkout .djj-checkout-tyc abbr.required {
	display: none;
}

/* Mensajes de error del checkout (ya con el formato estándar vinotinto,
   sección 10.4.3) — separación respecto al contenido de arriba. */
body.woocommerce-checkout .woocommerce-NoticeGroup-checkout {
	flex-shrink: 0;
	margin-bottom: 16px;
}

/* Mensajes de error individuales debajo de cada campo (ej. "Número de
   documento es un campo requerido.", `.checkout-inline-error-message` de
   WooCommerce), tamaño reducido un 20% (16px → 12.8px, venían con el gris
   genérico nativo). Color corregido a pedido del usuario: NO es el
   vinotinto estándar del sitio (#7A1E2C, 10.4.3) — es el rojo nativo de
   WooCommerce que YA se ve en el borde izquierdo del campo inválido
   (`.woocommerce-invalid input.input-text { box-shadow: #E2401C 2px 0 0
   inset }`, `woocommerce.css` de Storefront) para que ambos coincidan. */
body.woocommerce-checkout .checkout-inline-error-message {
	font-size: 12.8px;
	color: #E2401C;
}

/**
 * El error de Número de documento nace adentro de #billing_document_number_field
 * (form-row-last, empieza a la derecha de Tipo de documento) — a pedido del
 * usuario, tiene que arrancar alineado con el borde izquierdo de Tipo de
 * documento (form-row-first, el verdadero borde izquierdo de la fila), no
 * con su propio campo.
 *
 * ⚠️ Bug real — el primer intento (`margin-left: calc(-1 * (var(--djj-doctype-width) + 12px))`)
 * corrió el mensaje, pero no lo suficiente: las custom properties de CSS no
 * "recuerdan" dónde se definieron — son una sustitución de texto literal.
 * `--djj-doctype-width` contiene `calc((50% - 6px) * 0.76)`, y ese `50%`
 * se vuelve a resolver donde sea que la variable se USE, no donde se
 * declaró. En `#billing_document_type_field` (que comparte contenedor con
 * el 50%, el wrapper de campos) el resultado es correcto — pero el mensaje
 * de error vive DENTRO de `#billing_document_number_field` (un contenedor
 * mucho más angosto, ~173px), así que ahí el mismo `50%` se resolvía contra
 * ese ancho angosto, no contra el del wrapper — corría el mensaje bastante
 * menos de lo esperado. Solución: mover el cálculo a JS (`checkout-rules.js`,
 * `djjAlignDocNumberError`), que mide el ancho real en píxeles de Tipo de
 * documento con `getBoundingClientRect()` y no depende de en qué contenedor
 * se re-resuelva ningún porcentaje.
 */

@media (max-width: 767px) {
	body.woocommerce-checkout .woocommerce {
		width: 100vw;
	}
}

/* ==================== PÁGINA DE CONFIRMACIÓN (order-received) ==================== */

/**
 * ⚠️ Bug real, nunca antes reportado — este bloque completo llevaba toda la
 * sesión sin aplicarse. Estaba pensado para una página clara y centrada
 * (fondo crema, texto oscuro, 800px, sin el panel fijo del checkout), pero
 * perdía el empate de especificidad contra `body.woocommerce-checkout
 * .woocommerce` (13.1.3, el panel fijo oscuro) — esa regla tiene un
 * selector extra (`body`, un tipo) que le da más peso, y la página de
 * confirmación TAMBIÉN carga con `body.woocommerce-checkout` (WooCommerce
 * reutiliza la página del checkout para el estado "pedido recibido").
 * Resultado real, invisible hasta que alguien completó un pedido de
 * verdad: la confirmación se veía con el panel oscuro de siempre, pero con
 * el texto nativo de WooCommerce sin ningún color propio (gris/negro por
 * defecto) — casi ilegible sobre el fondo oscuro — y sin poder hacer
 * scroll (el contenido real mide ~1319px, la ventana fija del panel unos
 * 720px, y nada dentro tenía `overflow-y:auto`, a diferencia del formulario
 * del checkout que sí lo tiene, sección 13.1.3).
 *
 * En vez de pelear para que la idea original (página clara) vuelva a
 * ganar, se adapta el contenido al panel oscuro que YA es lo que se ve —
 * mismo criterio que el resto del checkout: texto crema/dorado, y scroll
 * dentro del panel fijo, igual que `form.checkout`.
 */
body.woocommerce-order-received .woocommerce-order {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	/* Vuelve al padding-top normal — "¡Gracias!"/"Tu pedido..." ya no van
	   debajo del isotipo, van AL LADO (izquierda), misma altura — ver
	   `.woocommerce-thankyou-order-received` más abajo, que reserva el
	   espacio a la derecha (no arriba) para el isotipo. */
	padding: 20px 28px 28px;
	box-sizing: border-box;
}

body.woocommerce-order-received .woocommerce-thankyou-order-received,
body.woocommerce-order-received .woocommerce-order-overview li,
body.woocommerce-order-received .woocommerce-order-details__title,
body.woocommerce-order-received .woocommerce-column__title,
body.woocommerce-order-received .woocommerce-table th,
body.woocommerce-order-received .woocommerce-table td,
body.woocommerce-order-received .woocommerce-customer-details p,
body.woocommerce-order-received p {
	color: var(--djj-cream);
	font-family: 'Poppins', sans-serif;
}

body.woocommerce-order-received .woocommerce-order-details__title,
body.woocommerce-order-received .woocommerce-column__title {
	font-family: 'Cormorant Garamond', serif;
	color: var(--djj-gold);
}

body.woocommerce-order-received .woocommerce-order-overview li strong,
body.woocommerce-order-received .woocommerce-table th {
	color: var(--djj-gold);
}

body.woocommerce-order-received a {
	color: var(--djj-gold);
}

body.woocommerce-order-received .woocommerce-order-details,
body.woocommerce-order-received .woocommerce-customer-details {
	border-top: 1px solid rgba(201, 162, 93, 0.25);
	padding-top: 20px;
	margin-top: 24px;
}

/* Isotipo, esquina superior derecha del panel — `position:fixed` (no
   depende de dónde caiga en el flujo de `.woocommerce-order`, que además
   tiene scroll propio) — mismo criterio que el resto de elementos
   anclados al viewport real en vez del flujo normal (panel, drawer). */
.djj-order-isotipo {
	position: fixed;
	top: 20px;
	right: 28px;
	width: 78px; /* 88px - 5px a cada lado (10px total) */
	height: 78px;
	/* `object-fit:cover` recorta de verdad (no achica toda la imagen) — la
	   caja se reduce 88px→78px y el navegador rellena ese cuadro más chico
	   recortando el margen exterior de la imagen, en vez de escalarla
	   completa hacia adentro. */
	object-fit: cover;
	z-index: 15;
}

/* "Gracias" / "Tu pedido ha sido recibido." — separados a 2 líneas
   (`display:block` en vez de `<br>`, más robusto si algún día el filtro
   se reutiliza en otro contexto). Base real medida en vivo: 16px — x2 y
   x1.5 pedidos explícitos del usuario. */
/* Al lado izquierdo del isotipo (no debajo) — mismo renglón superior.
   `padding-right` reserva el espacio del isotipo (78px de ancho + 28px de
   `right` del panel + ~16px de aire) para que el texto no quede debajo de
   él ni lo toque. */
body.woocommerce-order-received .woocommerce-thankyou-order-received {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding-right: 94px;
	box-sizing: border-box;
}

.djj-thankyou__title {
	display: block;
	font-family: 'Cormorant Garamond', serif;
	font-size: 32px; /* 16px x2 */
	font-weight: 600;
	color: var(--djj-gold);
}

.djj-thankyou__subtitle {
	display: block;
	font-size: 16.8px; /* 24px (16px x1.5) - 30% */
}

/* "Nota:" (djjoyeros_thankyou_cod_note_label) — mismo tratamiento visual
   que los eyebrows del checkout (dorado, mayúsculas, letras espaciadas),
   pegado al texto de instrucciones que sigue, no como un párrafo suelto. */
body.woocommerce-order-received .djj-order-note-label {
	color: var(--djj-gold);
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	margin: 0 0 4px !important;
}

/* Etiquetas del bloque de dirección ("Nombre:", "Dirección:", ...) — en
   dorado para diferenciarlas del dato, que hereda el crema estándar del
   resto de esta página (`body.woocommerce-order-received p`, más arriba). */
.djj-order-address strong {
	color: var(--djj-gold);
}

/* ⚠️ Bug real — el bloque "NÚMERO DEL PEDIDO/FECHA/TOTAL/MÉTODO DE PAGO" y
   la tabla "Detalles del pedido" son las únicas dos zonas de esta página
   con fondo CLARO nativo de Storefront (`#f8f8f8`/`#fdfdfd`, pensado para
   una página clara que nunca se ve — ver la nota de arriba sobre por qué
   este bloque entero no se aplicaba). El texto crema/dorado de las reglas
   de más arriba, pensado para el panel oscuro, quedaba casi invisible
   sobre ese fondo claro (peor caso: crema sobre blanco, ~1.06:1 de
   contraste). Texto negro acá, acotado a estas dos zonas — el resto de la
   página sigue en crema/dorado sobre el panel oscuro real. */
body.woocommerce-order-received .woocommerce-order-overview,
body.woocommerce-order-received .woocommerce-order-overview li,
body.woocommerce-order-received .woocommerce-order-overview li strong,
body.woocommerce-order-received .woocommerce-table,
body.woocommerce-order-received .woocommerce-table th,
body.woocommerce-order-received .woocommerce-table td {
	color: #000000;
}

/* Espacio entre "Tu pedido ha sido recibido." y el bloque
   NÚMERO/FECHA/TOTAL — Storefront trae `ul.order_details { margin:
   3.70633em 0 }` nativo (woocommerce.css), ~59.3px reales a este
   font-size — reducido, acotado al contexto de esta página. */
body.woocommerce-order-received .woocommerce-order-overview {
	margin-top: 16px !important;
}

/* "Método de pago" fuera del primer bloque (NÚMERO/FECHA/TOTAL) — a
   pedido explícito del usuario. El método de pago ya se repite en la
   tabla "Detalles del pedido" más abajo, así que no se pierde el dato. */
body.woocommerce-order-received .woocommerce-order-overview__payment-method {
	display: none;
}

/* ==================== HEADER MÓVIL (mismo breakpoint que Storefront: 767px) ==================== */

@media (max-width: 767px) {
	#masthead .custom-logo {
		max-height: 70px;
	}

	/* Alto del header móvil = alto REAL del logo (no siempre llega a los
	   70px de max-height — su ancho puede topar antes con el espacio
	   disponible junto al menú/carrito) + este padding. +2.5px arriba/abajo
	   acá, a pedido del usuario (alto del header +5px). */
	#masthead .site-branding {
		padding: 12.5px 0;
	}

	/* El toggle de menú y el carrito ya no forman una segunda fila: flotan
	   sobre la fila del logo, alineados uno junto al otro a la derecha.
	   OJO: se posicionan con un "top" fijo (no top:0;bottom:0;margin:auto),
	   porque #masthead es el contenedor de referencia y su alto CRECE cuando
	   el menú desplegable se abre — centrar con auto-margin los hacía bajar
	   junto con ese crecimiento. Un valor fijo los deja siempre en el mismo
	   lugar, con el menú abierto o cerrado.

	   `top:16.62px` = (73.24px de alto real del header - 40px del ícono) / 2
	   — centra el ícono a la altura media del header, a pedido del usuario.
	   El valor viejo (25px) centraba contra un alto de header de 90px, que
	   dejó de ser real desde el cambio de logo de esta sesión (ver el bug
	   documentado junto a `body { padding-top }`, más arriba).
	*/
	#site-navigation-menu-toggle.menu-toggle {
		position: absolute;
		top: 16.62px;
		right: 64px;
		margin: 0;
		float: none;
		max-width: none;
		width: 40px;
		height: 40px;
		padding: 0;
		border: none;
		background: transparent;
		box-shadow: none;
	}

	/* Storefront ya dibuja las 3 barras de la hamburguesa con estos pseudo-elementos;
	   solo las recentramos en el botón más pequeño y las pintamos en dorado. */
	#site-navigation-menu-toggle.menu-toggle::before,
	#site-navigation-menu-toggle.menu-toggle::after,
	#site-navigation-menu-toggle.menu-toggle span::before {
		left: 50%;
		/* +10% a pedido del usuario — 16px × 1.1 = 17.6px (móvil se queda en
		   este valor; el +10% adicional solo se aplicó en escritorio, ver
		   el bloque de escritorio arriba). */
		margin-left: -8.8px;
		width: 17.6px;
		background-color: var(--djj-gold) !important;
	}

	/* Oculta visualmente el texto "Menú" sin quitarlo para lectores de pantalla. */
	#site-navigation-menu-toggle.menu-toggle span {
		position: absolute;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
		border: 0;
	}

	#site-header-cart.site-header-cart {
		position: absolute;
		top: 16.62px; /* mismo cálculo que el menu-toggle, ver comentario arriba */
		right: 20px;
		margin: 0;
		height: 40px;
		display: flex;
		align-items: center;
	}

	#site-header-cart .cart-contents {
		position: relative;
		display: flex;
		align-items: center;
		justify-content: center;
		width: 40px;
		height: 40px;
		background: transparent;
		border: none;
		padding: 0;
		gap: 0;
	}

	/* Ícono de carrito, reemplazado por una bolsa — mismo cambio y misma
	   fuente que el bloque de escritorio (arriba), ver ese comentario para
	   el detalle completo. */
	#site-header-cart .cart-contents::before {
		content: "";
		display: block;
		/* +10% a pedido del usuario — 22px × 1.1 = 24.2px (móvil se queda en
		   este valor; el +10% adicional solo se aplicó en escritorio). */
		width: 24.2px;
		height: 24.2px;
		background-color: var(--djj-gold);
		transform: translateY(-3px);
		-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 26' fill='black'%3E%3Cpath d='M9.46552 25.2C16.9474 24.5623 20.1853 21.6541 19.9918 18.0061L19.45 8.37603V7.73828H14.7803V6.2842C14.7803 2.34287 13.4517 0.200012 10.3557 0.200012C7.01464 0.633686 5.58272 2.63624 5.47952 6.71787L5.46661 7.73828H0.513114L0.022914 16.6413C-0.273782 22.1388 2.28032 25.2 9.46552 25.2ZM10.1493 1.75613C12.1616 1.75613 13.0517 3.12093 13.0517 6.13113V7.73828H7.14365L7.15656 6.32246C6.96306 3.31226 8.08528 1.75613 10.1493 1.75613ZM1.64831 17.5087L2.04812 9.09032L5.44078 9.15409L5.38929 12.0112H7.10491L7.13074 9.1796L13.0646 9.28164V11.9985H14.7803V9.31991L17.8633 9.37093L18.3664 17.3046C18.6115 21.1439 14.4836 23.4781 9.85258 23.5801C4.30565 23.6949 1.49351 20.9653 1.64831 17.5087Z'/%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 20 26' fill='black'%3E%3Cpath d='M9.46552 25.2C16.9474 24.5623 20.1853 21.6541 19.9918 18.0061L19.45 8.37603V7.73828H14.7803V6.2842C14.7803 2.34287 13.4517 0.200012 10.3557 0.200012C7.01464 0.633686 5.58272 2.63624 5.47952 6.71787L5.46661 7.73828H0.513114L0.022914 16.6413C-0.273782 22.1388 2.28032 25.2 9.46552 25.2ZM10.1493 1.75613C12.1616 1.75613 13.0517 3.12093 13.0517 6.13113V7.73828H7.14365L7.15656 6.32246C6.96306 3.31226 8.08528 1.75613 10.1493 1.75613ZM1.64831 17.5087L2.04812 9.09032L5.44078 9.15409L5.38929 12.0112H7.10491L7.13074 9.1796L13.0646 9.28164V11.9985H14.7803V9.31991L17.8633 9.37093L18.3664 17.3046C18.6115 21.1439 14.4836 23.4781 9.85258 23.5801C4.30565 23.6949 1.49351 20.9653 1.64831 17.5087Z'/%3E%3C/svg%3E") center / contain no-repeat;
	}

	/* Oculta visualmente el texto "Carrito" sin quitarlo para lectores de pantalla. */
	#site-header-cart .cart-contents-label {
		position: absolute;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
		border: 0;
	}

	#site-header-cart .cart-contents .count {
		position: absolute;
		top: -4px;
		right: -8px;
		min-width: 16px;
		height: 16px;
		box-sizing: border-box;
		display: flex;
		align-items: center;
		justify-content: center;
		line-height: 1;
		font-size: 10px;
		padding: 0 3px;
		margin: 0;
	}
}

/* ==================== PÁGINAS LEGALES: Política de Privacidad y Términos y Condiciones ====================
   A pedido del usuario, en más de una vuelta — varios ajustes de formato,
   compartidos entre las dos páginas vía
   `body.privacy-policy, body.terminos-y-condiciones` (la primera ya la
   agrega sola WordPress por ser la página de privacidad real del sitio;
   la segunda es una clase propia, ver `djjoyeros_terms_page_body_class()`
   en functions.php). */

/* ⚠️ El título de Términos y Condiciones (`h1.entry-title`) estaba oculto
   de fábrica — hallazgo real, no un simple "faltaba alinearlo": la página
   se armó originalmente con Elementor (`_elementor_page_settings`,
   `hide_title:yes`), que Elementor aplica vía su propio CSS generado por
   página (`wp-content/uploads/elementor/css/post-26.css`, redefine la
   variable `--page-title-display` a `none` solo para esa página; el CSS
   global de Elementor la deja en `block` por defecto). Política de
   Privacidad no tiene ese mismo ajuste (nunca se armó con Elementor), por
   eso solo el título de Términos y Condiciones estaba invisible. Revertido
   acá con `!important` — más simple y confiable que tocar el postmeta de
   Elementor (que además podría regenerarse solo si alguien vuelve a abrir
   la página en el editor de Elementor). */
body.terminos-y-condiciones h1.entry-title {
	display: block !important;
}

/* Título alineado a la izquierda (a pedido del usuario — un intento
   anterior lo había puesto a la derecha, revertido acá), con la misma
   tipografía "estándar" (Poppins) que el resto del sitio usa para texto de
   interfaz — no la serif decorativa (Cormorant Garamond) que llevan los
   títulos en el resto del sitio. Mismo criterio para los títulos de cada
   sección (`<h2>`, ej. "1. Identificación del vendedor") — título Y
   contenido en la misma letra estándar, sin la serif de marca. El `<h2>`
   NO se alinea a la izquierda por esta regla porque ya lo está por
   defecto (hereda de `.entry-content`, sin `text-align` propio salvo el
   `justify` de los párrafos). */
body.privacy-policy .entry-title,
body.terminos-y-condiciones .entry-title {
	text-align: left;
	font-family: 'Poppins', sans-serif;
	/* Título principal a la mitad de su tamaño nativo. ⚠️ Primer intento
	   real, con un valor en `em` (1.853162952em, mitad de lo que parecía
	   ser la regla nativa de Storefront, `h1{font-size:3.706325903em}`) NO
	   dio la mitad real — dio 29.65px en vez de ~20.94px. La regla nativa
	   que de verdad se aplicaba no era esa (grepeada de memoria del CSS de
	   Storefront, sin confirmar en el navegador) sino otra, con `em`
	   compuestos por herencia anidada distinta. Corregido midiendo el
	   tamaño nativo REAL en el navegador antes de tocar nada
	   (`getComputedStyle`: 41.8868px) y fijando la mitad exacta en px, sin
	   depender de ninguna cadena de `em` que no se confirmó de verdad. */
	font-size: 20.9434px;
}

/* Subtítulos de sección (`<h2>`, los "numerales") en negrilla, y al mismo
   tamaño que los párrafos del contenido — bajados en 2 vueltas: primero a
   16px (igualando el tamaño nativo de los párrafos de ese momento), después
   a 12px junto con los párrafos mismos (ver la regla de `.entry-content p`
   más abajo, misma vuelta). El peso nativo del `<h2>` de Storefront es
   `font-weight:400` — sin negrilla — por eso hace falta declararla acá. */
body.privacy-policy .entry-content h2,
body.terminos-y-condiciones .entry-content h2 {
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	font-weight: 700;
}

/* Párrafos del contenido a 12px (bajados de 16px) — el título principal
   (`.entry-title`, arriba) NO se toca, a pedido explícito del usuario. */
body.privacy-policy .entry-content p,
body.terminos-y-condiciones .entry-content p {
	font-size: 12px;
}

/* Sangría de las viñetas (listas `<ul>` — ej. sección 1 "Identificación del
   vendedor", sección 5 "Medios de pago") reducida a la mitad. El indentado
   real no lo da `padding-left` (queda en 0 nativo) sino `margin-left` del
   `<ul>` (48px nativo, confirmado con `getComputedStyle` antes de tocar
   nada) — bajado a 24px. */
body.privacy-policy .entry-content ul,
body.terminos-y-condiciones .entry-content ul {
	margin-left: 24px;
}

/* Texto de las viñetas (`<li>`, ej. "Documento de identidad / NIT:...") a
   12px — quedaban en 16px nativo, sin tocar por la regla de párrafos de
   arriba (`.entry-content p`, que no alcanza a `<li>`, un selector
   distinto). */
body.privacy-policy .entry-content li,
body.terminos-y-condiciones .entry-content li {
	font-size: 12px;
}

/* Separación entre el header fijo y el título de la página — arrancó en
   ~0px reales (el `<header class="entry-header">` no traía ningún espacio
   propio arriba), se subió a 15px en una vuelta, y a pedido del usuario se
   aumentó 10px más acá (15px + 10px = 25px). */
body.privacy-policy .entry-header,
body.terminos-y-condiciones .entry-header {
	padding-top: 25px;
}

/* Espacio entre la fecha de "Última actualización" (ahora al final de la
   página, ver 15) y el footer — reducido a la mitad en 2 vueltas seguidas:
   132.28px nativo → 66.14px → 33.07px.
   ⚠️ 3 intentos reales fallidos antes de este, todos por el mismo error de
   fondo: tratar de PREDECIR el resultado ajustando `margin-bottom` en
   distintos puntos de la cadena de contenedores anidados (el párrafo,
   `<article>`, `.content-area`), esperando que los valores se sumen o
   colapsen de forma predecible. Cada intento midió un resultado real
   distinto al calculado (60.47px, luego 58.86px, luego 74.94px, buscando
   siempre 66.14px o 33.07px según la vuelta) — incluso agregando
   `display:flow-root` a `.entry-content` (que si contuvo el margen del
   párrafo dentro de `.entry-content`, confirmado con
   `getBoundingClientRect`) el total seguía sin coincidir, porque
   `.content-area` (`#primary`, `float:left`) mostraba ~41.87px de alto
   real de más respecto a su único hijo (`<main>`) sin que **ninguna regla
   CSS real** (confirmado recorriendo `document.styleSheets` con
   `cssRules`, no adivinado) le pusiera padding, margin ni altura — un
   comportamiento del propio layout de floats en este contexto específico,
   sin una causa aislable con los mismos métodos que sí funcionaron para
   otros bugs de este proyecto (10.4h, 13.1.3k, etc.).
   Solución robusta que no depende de entender esa causa: en vez de seguir
   ajustando la cadena de contenedores, se mueve el footer directo con un
   `margin-top` negativo, calculado sobre el espacio 100% nativo original
   (132.28125px, medido antes de tocar nada) menos el objetivo final
   (33.0703125px) — un solo número, un solo lugar, sin depender de cómo
   colapsen o no los márgenes de en medio. */
body.privacy-policy #colophon,
body.terminos-y-condiciones #colophon {
	margin-top: -93.5625px;
}

/* ⚠️ Bug real — el `margin-top` de arriba se calibró SOLO en escritorio
   (1280px): en móvil (375px) el mismo valor fijo dejaba el footer
   **superpuesto** sobre el contenido (`-8.81px` de "espacio", confirmado
   con `getBoundingClientRect` antes de dar el ajuste por bueno en los dos
   anchos — no solo en el que se probó primero). La causa de fondo del
   "alto de más" de `.content-area` (13.1.3l/README) varía con el ancho de
   pantalla, así que un solo valor fijo en `px` no sirve en los dos
   breakpoints — recalibrado por separado para móvil. */
@media (max-width: 767px) {
	body.privacy-policy #colophon,
	body.terminos-y-condiciones #colophon {
		margin-top: -51.6796875px;
	}
}

/* Espacio entre el fin de un párrafo y el numeral de la sección siguiente,
   reducido un 60% a pedido del usuario. Storefront trae
   `p + h2, p + h3, ... { margin-top: 2.29068em }` (~73.3px reales, nativo,
   pensado para separar secciones en cualquier página de contenido) — acá
   pasa a ~29.32px (73.3 x 0.4). Ya se había reducido antes solo para
   Política de Privacidad (`body.privacy-policy`) — Términos y Condiciones
   seguía con el valor nativo completo sin tocar (73.3px, confirmado con
   `getComputedStyle` antes de asumir que ya estaba parejo entre las dos
   páginas). Unificado acá a las dos con el mismo valor. */
body.privacy-policy .entry-content h2,
body.terminos-y-condiciones .entry-content h2 {
	margin-top: 29.32px;
}

/* Contenido justificado (a los dos bordes, no solo alineado a la izquierda)
   — en el contenedor, así hereda a párrafos y listas por igual sin listar
   cada selector hijo. */
body.privacy-policy .entry-content,
body.terminos-y-condiciones .entry-content {
	text-align: justify;
}
