/* ============================================================
   CM DESCANSO · COMPONENTES  ·  v3
   Libreria reutilizable en toda la web (como el sistema de OKA).
   Aplicar la clase en "CSS Classes" del widget/contenedor en Elementor.
   ============================================================ */

/* ===== BOTONES ===== */
.cmd-btn { display:inline-flex; align-items:center; justify-content:center; gap:.55em;
  font-family:var(--cmd-font-body); font-size:var(--cmd-fs-sm); font-weight:500; line-height:1;
  padding:.95em 1.5em; border-radius:var(--cmd-r-sm); border:1px solid transparent; cursor:pointer; text-decoration:none;
  transition:background var(--cmd-dur) var(--cmd-ease), color var(--cmd-dur) var(--cmd-ease), border-color var(--cmd-dur) var(--cmd-ease), transform var(--cmd-dur) var(--cmd-ease); }
.cmd-btn:active { transform:translateY(1px); }
.cmd-btn-primary { background:var(--cmd-green); color:var(--cmd-on-dark); }
.cmd-btn-primary:hover { background:var(--cmd-green-deep); color:var(--cmd-on-dark); }
.cmd-btn-dark { background:var(--cmd-ink); color:var(--cmd-on-dark); }
.cmd-btn-ghost { background:transparent; color:var(--cmd-ink); border-color:var(--cmd-line-strong); }
.cmd-btn-ghost:hover { background:var(--cmd-ink); color:var(--cmd-on-dark); border-color:var(--cmd-ink); }

/* Enlace de texto con flecha (OKA) */
.cmd-link { display:inline-flex; align-items:center; gap:.4em; font-size:var(--cmd-fs-sm); font-weight:500;
  color:var(--cmd-ink); text-transform:uppercase; letter-spacing:.08em; text-decoration:none; }
.cmd-link::after { content:"\2192"; transition:transform var(--cmd-dur) var(--cmd-ease); }
.cmd-link:hover::after { transform:translateX(4px); }

/* ===== TAGS ===== */
.cmd-tag { display:inline-block; font-size:var(--cmd-fs-2xs); font-weight:500; letter-spacing:.08em;
  text-transform:uppercase; padding:.35em .6em; border:1px solid var(--cmd-line-strong); border-radius:var(--cmd-r-sm); color:var(--cmd-ink); }
.cmd-tag-trust { background:var(--cmd-green-soft); color:var(--cmd-green-deep); border-color:transparent; }
.cmd-tag-clay  { background:var(--cmd-clay-soft); color:var(--cmd-clay); border-color:transparent; }

/* ===== GLASS SUAVE (uso con cuentagotas: 1-2 por vista) ===== */
.cmd-glass {
  background:var(--cmd-glass-fill);
  -webkit-backdrop-filter:var(--cmd-glass-blur); backdrop-filter:var(--cmd-glass-blur);
  border:1px solid var(--cmd-glass-border); border-radius:14px;
  box-shadow: inset 0 1px 0 var(--cmd-glass-highlight), 0 2px 10px var(--cmd-glass-shadow);
  transform:translateZ(0);
}
/* Badge de glass flotante (la nota de cristal "firma", sobre una foto) */
.cmd-glass-badge {
  display:inline-flex; align-items:center; gap:.5em; padding:.55em .9em; border-radius:var(--cmd-r-pill);
  font-size:var(--cmd-fs-xs); font-weight:500; color:var(--cmd-ink);
  background:var(--cmd-glass-fill-strong);
  -webkit-backdrop-filter:var(--cmd-glass-blur); backdrop-filter:var(--cmd-glass-blur);
  border:1px solid var(--cmd-glass-border);
  box-shadow: inset 0 1px 0 var(--cmd-glass-highlight), 0 2px 10px var(--cmd-glass-shadow);
}
/* Barra pegajosa de compra en glass suave */
.cmd-glass-bar {
  background:var(--cmd-glass-fill-strong);
  -webkit-backdrop-filter:blur(12px) saturate(125%); backdrop-filter:blur(12px) saturate(125%);
  border-top:1px solid var(--cmd-glass-border);
  box-shadow: inset 0 1px 0 var(--cmd-glass-highlight), 0 -4px 16px rgba(43,38,32,.06);
  transform:translateZ(0);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .cmd-glass, .cmd-glass-badge, .cmd-glass-bar { background:rgba(251,248,242,.97); }
}
@media (prefers-reduced-transparency: reduce) {
  .cmd-glass, .cmd-glass-badge, .cmd-glass-bar { -webkit-backdrop-filter:none; backdrop-filter:none; background:rgba(251,248,242,.97); }
}

/* ===== MARCA DIBUJADA A MANO (usar UNA sola vez, bajo el nombre del producto) ===== */
.cmd-handmark { display:block; width:clamp(120px,40%,210px); height:12px; margin-top:-2px; color:var(--cmd-clay); }
.cmd-handmark path { stroke:currentColor; stroke-width:2.4; fill:none; stroke-linecap:round; }

/* ===== REGLAS FINAS (specs editoriales, no tarjetas) ===== */
.cmd-rule-row { display:flex; justify-content:space-between; align-items:baseline; gap:1.5rem;
  border-bottom:1px solid var(--cmd-line); padding-block:.85rem; }
.cmd-rule-row:last-child { border-bottom:0; }
.cmd-rule-row .k { color:var(--cmd-muted); font-size:var(--cmd-fs-sm); }
.cmd-rule-row .v { color:var(--cmd-ink); font-size:var(--cmd-fs-sm); text-align:right; }

/* ===== BANNER EDITORIAL (titular gigante sobre foto, estilo OKA) ===== */
.cmd-editorial { position:relative; min-height:clamp(380px,52vw,640px); display:flex;
  flex-direction:column; justify-content:flex-end; align-items:flex-start;
  border-radius:var(--cmd-r-lg); overflow:hidden; }
.cmd-editorial::after { content:""; position:absolute; inset:0;
  background:linear-gradient(180deg, rgba(30,26,21,.05) 0%, rgba(30,26,21,.0) 35%, rgba(30,26,21,.55) 100%); }
.cmd-editorial .cmd-editorial-bg { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.cmd-editorial .cmd-editorial-in { position:relative; z-index:2; padding:clamp(1.5rem,4vw,3.5rem); max-width:18ch; }
.cmd-editorial .cmd-editorial-in .cmd-mega,
.cmd-editorial .cmd-editorial-in h2 { color:var(--cmd-on-dark); margin:0; }
.cmd-editorial .cmd-eyebrow { color:rgba(245,240,231,.8); margin-bottom:.6rem; display:block; }

/* ===== BLOQUE HISTORIA (asimetrico: foto + copy, editorial/humanista) ===== */
.cmd-story { display:grid; grid-template-columns:1.25fr 1fr; gap:clamp(2rem,5vw,5rem); align-items:center; }
.cmd-story.is-reverse { grid-template-columns:1fr 1.25fr; }
.cmd-story.is-reverse .cmd-story-media { order:2; }
.cmd-story-media img { width:100%; border-radius:var(--cmd-r-md); }
.cmd-story-body { max-width:46ch; }
.cmd-story-body h2 { margin:0 0 var(--cmd-s4); }
.cmd-story-body p { color:var(--cmd-text); }

/* ===== TARJETA DE PRODUCTO (foto que flota, sin marco) ===== */
.cmd-pcard { position:relative; display:block; text-decoration:none; color:inherit; }
.cmd-pcard__media { position:relative; aspect-ratio:4/5; background:var(--cmd-stone); border-radius:var(--cmd-r-md); overflow:hidden; }
.cmd-pcard__media img { width:100%; height:100%; object-fit:cover; transition:transform var(--cmd-dur-slow) var(--cmd-ease); }
.cmd-pcard:hover .cmd-pcard__media img { transform:scale(1.03); }
.cmd-pcard__title { font-family:var(--cmd-font-display); color:var(--cmd-ink); font-size:1.2rem; font-weight:500; margin:.6rem 0 .15rem; }
.cmd-pcard__price { font-weight:600; color:var(--cmd-ink); }

/* ===== BANDA DE CONFIANZA ===== */
.cmd-trust { display:flex; flex-wrap:wrap; gap:var(--cmd-s6); align-items:center; justify-content:center;
  background:var(--cmd-ink); color:var(--cmd-on-dark); padding:var(--cmd-s4) var(--cmd-s5); }
.cmd-trust__item { display:inline-flex; align-items:center; gap:.6em; font-size:var(--cmd-fs-sm); color:var(--cmd-on-dark); }

/* ===== ACORDEON ===== */
.cmd-acc { border-top:1px solid var(--cmd-line); }
.cmd-acc__item { border-bottom:1px solid var(--cmd-line); }
.cmd-acc__head { display:flex; justify-content:space-between; align-items:center; width:100%; background:none; border:0; cursor:pointer;
  padding:var(--cmd-s4) 0; font-family:var(--cmd-font-body); font-size:var(--cmd-fs-body); font-weight:500; color:var(--cmd-ink); text-align:left; }

/* ===== BANDAS DE SECCION ===== */
.cmd-band-paper { background:var(--cmd-paper); }
.cmd-band-panel { background:var(--cmd-panel); }
.cmd-band-band  { background:var(--cmd-band); }
.cmd-band-ink   { background:var(--cmd-ink); color:var(--cmd-on-dark); }
.cmd-band-green { background:var(--cmd-green); color:var(--cmd-on-dark); }

@media(max-width:880px){
  .cmd-story, .cmd-story.is-reverse { grid-template-columns:1fr; gap:1.5rem; }
  .cmd-story.is-reverse .cmd-story-media { order:0; }
}

/* ============================================================
   MOTION (F6 N2, goal nocturno 9/10-jul) · la capa "hecha por un humano"
   Reveals al entrar en viewport + hovers con intencion + detalles finos.
   Filosofia OKA: sutil, lento (300-600ms, ease-out), UNA idea por elemento.
   Doble seguro de accesibilidad: (a) el estado oculto inicial del reveal
   solo se aplica con prefers-reduced-motion:no-preference (si el usuario
   pide menos movimiento, los elementos SIEMPRE estan visibles, nunca
   arrancan en opacity:0); (b) el JS del observer (functions.php, wp_footer)
   comprueba matchMedia y no anade ninguna clase si hay reduced-motion.
   Solo transform/opacity (nunca propiedades de layout): cero layout thrashing.
   ============================================================ */

/* ---- Reveal fade-up: el JS marca .cmd-reveal en una lista curada de
   selectores ya existentes (titulares, tiles, cards, bloques editoriales)
   y anade .is-visible al entrar en viewport. Stagger corto via --cmd-rv-d
   (variable inline puesta por el propio JS, en pasos de 70ms). ---- */
@media (prefers-reduced-motion: no-preference) {
  .cmd-reveal {
    opacity: 0;
    transform: translateY(10px);
    transition: opacity .6s var(--cmd-ease-out), transform .6s var(--cmd-ease-out);
    transition-delay: var(--cmd-rv-d, 0ms);
  }
  .cmd-reveal.is-visible { opacity: 1; transform: none; }
}

/* ---- Hover de foto en tarjeta de producto: mismo lenguaje en las 3
   rejillas nativas de Woo del sitio (home bestsellers, archivo/tienda,
   relacionados de la PDP) + tiles de categoria de la home. Zoom lento,
   nunca brusco. ---- */
.cmd-home-best-w ul.products li.product a img,
.cmd-arch-grid-w ul.products li.product a img,
.cmd-related ul.products li.product a img,
.cmd-home-cat-img img {
  transition: transform .6s var(--cmd-ease-out);
}
.cmd-home-best-w ul.products li.product:hover a img,
.cmd-arch-grid-w ul.products li.product:hover a img,
.cmd-related ul.products li.product:hover a img,
.cmd-home-cat:hover .cmd-home-cat-img img {
  transform: scale(1.035);
}

/* ---- Fondo para los recortes. Las 4 almohadas del catalogo NO tienen ni una
   foto de ambiente: Sonpura solo entrega PNG del producto recortado sobre
   transparente. Sobre el crema del sistema, una almohada blanca sobre fondo
   casi blanco es literalmente una mancha (era el primer bloque de /tienda/).
   Un fondo arena por debajo hace que el objeto recorte, sin tocar las fotos
   de ambiente, que lo tapan por completo. Vale para cualquier recorte futuro.

   Especificidad a proposito (R26): el design system se encola a prioridad 5,
   ANTES del custom_css por-pagina. `.cmd-home-cat-img img` (0,2,1) existe alli
   con background:var(--cmd-panel); un empate lo gana el que carga despues, o
   sea la pagina. Con `.cmd-scope` delante (0,3,1) gana esta. ---- */
.cmd-scope .cmd-home-cat-img img,
.cmd-scope ul.products li.product a img,
.cmd-scope .woocommerce-product-gallery img {
  background-color: var(--cmd-band);
}

/* Las almohadas son SIEMPRE packshot recortado (Sonpura no da otra cosa). Un
   packshot apaisado dentro de una tarjeta vertical con object-fit:cover se
   amplia hasta salirse: se ve un trozo de tela blanca, no una almohada. Con
   `contain` + aire, el objeto se ve entero y flota sobre la arena. La clase
   product_cat-<slug> la pone WooCommerce sola, asi que esto vale para las 4
   almohadas de hoy y para las que se anadan manana.

   Especificidad: el custom_css de cada pagina trae
   `.cmd-arch-grid-w ul.products li.product a img` = (0,3,4). Un
   `.cmd-scope li.product.product_cat-almohadas a img` es (0,3,2) y PIERDE:
   mismo numero de clases, menos elementos. Solo el padding llegaba a aplicar,
   porque nadie se lo disputaba. Con `ul.products` delante subimos a (0,4,4).

   Solo en las rejillas GRANDES: en la miniatura de 60px del cross-sell
   ("Combinalo con") un contain con 10% de padding deja la almohada del tamano
   de una lenteja y la tarjeta parece vacia. */
.cmd-home-best-w ul.products li.product.product_cat-almohadas a img,
.cmd-arch-grid-w ul.products li.product.product_cat-almohadas a img,
.cmd-related ul.products li.product.product_cat-almohadas a img {
  object-fit: contain;
  padding: 10%;
  background-color: var(--cmd-band);
}

/* ---- La galeria acompana a la compra. La columna de la izquierda acababa
   600px antes que la derecha (medida, precio, add-to-cart, envio, cross-sell):
   un agujero enorme al lado del buy-box, justo donde el comprador decide.
   Sticky en escritorio: la foto sigue mientras eliges medida. En movil las
   columnas se apilan y esto no aplica. ---- */
@media (min-width: 1024px) {
  .cmd-scope .cmd-pdp-gallery {
    position: sticky;
    top: 104px;              /* header sticky (R15) + aire */
    align-self: start;
  }
}

/* ============================================================
   HUECOS MUERTOS. Dos bloques de la PDP se comian media pagina:

   1. La guia "Como elegir" venia de [cmd_guia] (shortcode) y su
      .cmd-guide-grid computaba display:block -> los 3 criterios se
      apilaban a 1300px de ancho cada uno, pegados al borde izquierdo.
      En la HOME se veia bien porque alli la guia son contenedores de
      Elementor, no el shortcode: el CSS de columnas vivia en el
      custom_css de la home y nadie lo habia llevado al sistema.
   2. .cmd-specs2-in medía 840px de 1440, alineada a la izquierda:
      600px muertos al lado de la ficha tecnica. Ahora es una rejilla
      de dos columnas (titulo | acordeon), que es lo que pedia el
      contenido, y va centrada.

   Vive aqui, en el design system, y no en el custom_css de una pagina:
   asi el shortcode se ve igual en cualquier plantilla que lo use.
   ============================================================ */

/* La guia: 3 criterios en columnas, sin numerar (no son una secuencia). */
.cmd-scope .cmd-guide-w,
.cmd-scope .cmd-guide-grid {
  width: 100%;
  min-width: 0;
}
.cmd-scope .cmd-guide-head {
  margin-bottom: clamp(1.75rem, 3vw, 2.75rem);
}
.cmd-scope .cmd-guide-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(1.75rem, 3.2vw, 3rem);
  align-items: start;
}
.cmd-scope .cmd-guide-i { min-width: 0; }
.cmd-scope .cmd-guide-h h3 { margin: 0 0 .55rem; }
.cmd-scope .cmd-guide-t p { margin: 0; }

/* La ficha tecnica: titulo a la izquierda, acordeon a la derecha.
   `!important` en display/width por R21: Elementor pone su propio flex
   sobre todo .elementor-element y un empate de especificidad lo gana el. */
.cmd-scope .cmd-specs2-in {
  max-width: 1200px;
  margin-inline: auto !important;
}
@media (min-width: 1024px) {
  .cmd-scope .cmd-specs2-in {
    display: grid !important;
    grid-template-columns: minmax(240px, 340px) minmax(0, 1fr);
    column-gap: clamp(2.5rem, 6vw, 6rem);
    align-items: start;
    width: 100% !important;
  }
  .cmd-scope .cmd-specs2-in > .cmd-specs2-h { grid-column: 1; align-self: start; }
  .cmd-scope .cmd-specs2-in > .cmd-acc {
    grid-column: 2;
    width: 100% !important;
    margin-top: 0 !important;
  }
  /* el titulo acompana al acordeon mientras se lee, sin saltar */
  .cmd-scope .cmd-specs2-in > .cmd-specs2-h { position: sticky; top: 104px; }
}
@media (prefers-reduced-motion: reduce) {
  .cmd-scope .cmd-specs2-in > .cmd-specs2-h { position: static; }
}

/* ---- Enlaces editoriales (cuerpo de lectura, respuestas del acordeon):
   subrayado que se "dibuja" en vez de aparecer de golpe. Solo texto de
   contenido, NUNCA nav/botones/chips (ya tienen sus propios estados). ---- */
.cmd-scope .cmd-read-body a,
.cmd-scope .cmd-acc-tx a,
.cmd-scope .cmd-story-body a {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 0 100%;
  background-repeat: no-repeat;
  background-size: 0% 1px;
  transition: background-size .4s var(--cmd-ease-out);
}
.cmd-scope .cmd-read-body a:hover,
.cmd-scope .cmd-acc-tx a:hover,
.cmd-scope .cmd-story-body a:hover {
  background-size: 100% 1px;
}

/* ---- Chips (selector de medida PDP, subcategorias de archivo): lift
   sutil + borde que se marca, ya tienen fondo/color propios por contexto. ---- */
.cmd-archchip, .cmd-swatch, .cmd-chip {
  transition: background .2s var(--cmd-ease-out), border-color .2s var(--cmd-ease-out), transform .2s var(--cmd-ease-out);
}
.cmd-archchip:hover, .cmd-swatch:hover, .cmd-chip:hover { transform: translateY(-1px); }

/* ---- Botones: mismo lenguaje de "lift" sutil en hover (ya tienen cambio
   de color; se anade profundidad, no solo tinte). G4-polish: el lift cubre
   TODOS los CTA del sitio (add-to-cart de la PDP, botones de tarjeta del
   archivo/related, newsletter), no solo los de cuenta/checkout: un unico
   lenguaje de boton en toda la web. ---- */
.cmd-btn:hover, .cmd-myacc .button:hover, .cmd-myacc button[type=submit]:hover,
body.woocommerce-checkout .wc-block-components-checkout-place-order-button:hover,
body.woocommerce-cart .wc-block-cart__submit-button:hover,
.cmd-scope .single_add_to_cart_button:hover,
.cmd-scope ul.products li.product .button:hover,
.cmd-nlform button:hover,
.cmd-home-hero-cta .wp-block-button__link:hover {
  box-shadow: 0 4px 14px rgba(26,28,22,.10);
}

/* ============================================================
   GLASS V2 · receta PRO (G5-polish). Tres capas como el Liquid Glass
   de Apple, en CSS puro con fallback (la refraccion SVG real solo es
   fiable en Chromium; no se usa en produccion):
     1. FROST: backdrop blur(26) + saturate(190%) + brightness → el fondo
        se convierte en color, no en gris.
     2. SHEEN: destello diagonal sutil en el propio background.
     3. RIM: ::after con borde de 1px en DEGRADADO (luz arriba-izquierda,
        sombra en la diagonal, luz de rebote abajo) via mask-composite.
   Superficies de chrome: barra sticky de compra, badge sobre foto,
   dropdown del header, header al scrollear, drawer del mini-cart,
   chips de subcategoria. Nunca tarjetas de contenido.
   ============================================================ */
.cmd-glass2 {
  position: relative;
  background: var(--cmd-glass2-sheen), var(--cmd-glass2-fill);
  -webkit-backdrop-filter: var(--cmd-glass2-blur); backdrop-filter: var(--cmd-glass2-blur);
  border: 1px solid transparent;
  box-shadow: var(--cmd-glass2-edge), var(--cmd-glass2-shadow);
  transform: translateZ(0);
}
.cmd-glass2::after {
  content: ""; position: absolute; inset: -1px; border-radius: inherit;
  padding: 1px; pointer-events: none;
  background: var(--cmd-glass2-rim);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .cmd-glass2 { background: rgba(251, 248, 242, .96); }
}
@media (prefers-reduced-transparency: reduce) {
  .cmd-glass2 { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(251, 248, 242, .96); }
}
@media (prefers-contrast: more) {
  .cmd-glass2 { background: rgba(251, 250, 246, .98); border-color: var(--cmd-line-strong); }
}

/* ---- Respuesta al PULSAR (skill Apple: feedback en pointer-down, nunca solo
   al soltar). Todos los CTA del camino de compra se hunden 1px al presionar. ---- */
.cmd-scope .single_add_to_cart_button:active,
.cmd-scope ul.products li.product .button:active,
.cmd-buybar-cta:active,
.cmd-nlform button:active,
body.woocommerce-checkout .wc-block-components-checkout-place-order-button:active,
body.woocommerce-cart .wc-block-cart__submit-button:active,
.wc-block-mini-cart__footer .wc-block-mini-cart__footer-checkout:active {
  transform: translateY(1px);
}

/* ---- Imagenes: fade-in al terminar de cargar (evita el "pop" del
   lazyload). El JS anade .cmd-img-loaded cuando el <img> dispara 'load'
   (o de inmediato si ya estaba cacheada/complete). ---- */
/* El `html.cmd-motion` lo pone el propio script de motion al arrancar. Sin el, este
   bloque no existe y las imagenes se ven SIEMPRE. Antes el opacity:0 estaba en CSS
   puro y la visibilidad del contenido dependia de que un script llegara a correr:
   si fallaba, la web salia sin fotos (impeccable: skill-motion-reveal-safety).

   NO llamar a esta clase `cmd-js`: la plantilla de la PDP ya tiene un
   `.cmd-js{display:none}` (oculta el <select> nativo de medida cuando los chips
   estan activos). Ponersela al <html> dejo TODAS las fichas de producto en
   blanco. Antes de crear una clase global, buscarla en el custom_css servido. */
@media (prefers-reduced-motion: no-preference) {
  html.cmd-motion .cmd-scope img:not(.cmd-logo-img):not(.cmd-flogo-img) {
    opacity: 0;
    transition: opacity .5s var(--cmd-ease-out);
  }
  /* !important necesario: los 2 :not() de la regla de arriba suman mas
     especificidad que esta aunque venga despues; sin esto las imagenes se
     quedaban en opacity:0 para siempre pese a llevar ya la clase
     .cmd-img-loaded (bug encontrado en la propia verificacion de esta capa:
     nunca fiarse del orden de cascada cuando hay :not()). */
  html.cmd-motion .cmd-scope img.cmd-img-loaded,
  html.cmd-motion .cmd-scope img.cmd-img-skip { opacity: 1 !important; }
}

/* ============================================================
   MOTION CON PROPOSITO. Dos graficos, no un efecto suelto.
   Ambos parten de su estado FINAL: si no hay JS, o el usuario pide
   menos movimiento, el dato se ve igual. El motion nunca es el que
   decide si la informacion existe.
   ============================================================ */

/* 1. La escala de firmeza se dibuja de "Suave" hasta el valor real.
   Se anima scaleX (compositado), nunca `width` ni `left`. */
.cmd-scope .cmd-firm-scale { position: relative; }
.cmd-scope .cmd-firm-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--cmd-firm-pos, 55%);
  border-radius: inherit;
  background: var(--cmd-green);
  transform-origin: left center;
}
@media (prefers-reduced-motion: no-preference) {
  html.cmd-motion .cmd-scope .cmd-firm-fill {
    transform: scaleX(0);
    transition: transform .9s var(--cmd-ease-out);
  }
  html.cmd-motion .cmd-scope .cmd-firm-scale.is-drawn .cmd-firm-fill { transform: scaleX(1); }
  /* el punto llega con la barra, no antes */
  html.cmd-motion .cmd-scope .cmd-firm-dot {
    opacity: 0;
    transition: opacity .3s var(--cmd-ease-out) .6s;
  }
  html.cmd-motion .cmd-scope .cmd-firm-scale.is-drawn .cmd-firm-dot { opacity: 1; }
}

/* 2. Las capas del colchon: secuencia real (fuera -> dentro), no un fade
   uniforme. Cada capa entra desde su propio lado con su retardo. */
@media (prefers-reduced-motion: no-preference) {
  html.cmd-motion .cmd-scope .cmd-capa-in {
    opacity: 0;
    transform: translate3d(14px, 0, 0);
    transition: opacity .55s var(--cmd-ease-out) var(--cmd-capa-d, 0ms),
                transform .55s var(--cmd-ease-out) var(--cmd-capa-d, 0ms);
  }
  html.cmd-motion .cmd-scope .cmd-capa-in.is-visible {
    opacity: 1;
    transform: none;
  }
}

/* ---- Detalles de artesania: foco visible con el acento del sistema,
   color de seleccion de texto, scroll suave a anclas (acordeones,
   #como-elegir de la PDP). ---- */
.cmd-scope :focus-visible {
  outline: 2px solid var(--cmd-green);
  outline-offset: 2px;
}
.cmd-scope ::selection { background: var(--cmd-green-soft); color: var(--cmd-ink); }
html:has(body.cmd) { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html:has(body.cmd) { scroll-behavior: auto; }
}

/* ---- G9-polish · ligaduras fuera en titulos de UI pequeños ----
   Fraunces liga "fi" ("Base fija" → "Base ïija" visual) a cuerpos chicos:
   el dato en BD es correcto, es tipografia. En titulos de tarjeta/barra
   (utilitarios, no display) las ligaduras no aportan y confunden. */
.woocommerce-loop-product__title,
.cmd-buybar-name,
.cmd-upsell .woocommerce-loop-product__title,
.cmd-related .woocommerce-loop-product__title {
  font-variant-ligatures: no-common-ligatures;
}
