/*
 * Spinshop ring configurator.
 *
 * Everything is namespaced under .spinshop-configurator and every value is a
 * custom property, because this gets dropped into somebody else's WordPress
 * theme and must neither leak nor be impossible to retheme.
 *
 * No webfonts anywhere in here. WordPress.org forbids loading external
 * resources, so type comes from the host theme or from a font the shop already
 * ships - never from a CDN.
 */

/* ==========================================================================
   THE THEMING CONTRACT
   --------------------------------------------------------------------------
   Everything below this block is STRUCTURE: layout, states, focus rings,
   responsive behaviour. A theme must not need to touch any of it.

   Everything IN this block is a token, and a theme overrides tokens only. That
   split is what lets the same plugin sit in a jeweller's shop and in a mug shop
   without either of them forking the stylesheet.

   The defaults here are deliberately PLAIN. A plugin that arrives with a strong
   opinion looks broken in every shop whose taste differs, so out of the box it
   borrows the host theme's typography (font: inherit) and stays in neutral
   greys. Shops that want a look ship a theme - see themes/une.css.

   The one thing NOT up for negotiation is the dark stage. Metal has no colour
   of its own; it is entirely made of what it reflects, and on a light backdrop
   it renders as grey plastic. --sc-stage can be retinted, not lightened.
   ========================================================================== */

.spinshop-configurator {
  --sc-ink: #1c1c1e;
  --sc-ink-soft: #62636a;
  --sc-ink-faint: #9a9ba3;
  --sc-paper: #ffffff;
  --sc-paper-warm: #f2f2f4;
  --sc-line: #dcdce1;
  /* Tres paradas, no dos: el nucleo es la parte iluminada de la vineta y tiene
     que ser un token como las otras dos. Estaba escrito duro en .sc-stage, asi
     que un tema podia retintar el borde y el medio pero no el centro - y el
     centro se quedaba en un gris azulado que no era de ninguna paleta. */
  --sc-stage-core: #1d2027;
  --sc-stage: #16181c;
  --sc-stage-edge: #0b0c0f;
  --sc-accent: #1c1c1e;
  /* El hover del boton de compra estaba escrito duro en .sc-cta, y en un hex
     que no era de ninguna paleta. Es un token porque el color de un boton de
     compra pertenece a la tienda, no al plugin. */
  --sc-accent-hover: #2a2a30;
  --sc-warn: #9c3b2f;

  /* Two radii, because controls and panels want different ones and a theme with
     one knob has to compromise on both. */
  --sc-radius: 2px;
  --sc-radius-lg: var(--sc-radius);
  /* Y un tercero, solo para el boton de compra. Colgaba de --sc-radius, que se
     fija pensando en steppers de 2.5rem: la forma del CTA salia de una decision
     tomada para otra cosa. Vale lo mismo por defecto, asi que nada cambia; lo
     que gana es que una tienda puede darle forma al boton mas importante de la
     pagina sin arrastrar con el todos los controles. */
  --sc-radius-cta: var(--sc-radius);

  /* Inherited on purpose: a configurator set in a font the rest of the shop
     does not use is the tell of a bolted-on plugin. */
  --sc-serif: inherit;
  --sc-sans: inherit;

  --sc-display-size: clamp(1.5rem, 2.6vw, 1.85rem);
  --sc-display-weight: 600;
  --sc-display-spacing: -0.01em;

  /*
   * EL TAMANO DE LA ADVERTENCIA LEGAL, Y POR QUE YA NO ES EL DEL PRECIO.
   *
   * Varias jurisdicciones exigen que la advertencia que quita el derecho a
   * devolucion se muestre a un tamano NO INFERIOR al del precio. En Chile lo
   * fija el Decreto N°52 del Ministerio de Economia, vigente desde el
   * 28-feb-2025, para los bienes personalizados; Europa tiene reglas de
   * prominencia parecidas.
   *
   * Los dos compartieron UN token durante unas horas el 2026-08-19, justamente
   * para que la igualdad no dependiera de que nadie la rompiera: sin palanca
   * separada, no hay forma de dejar la advertencia mas chica.
   *
   * ── ESA GARANTIA SE RETIRO A PETICION DE PIERO, el 2026-08-19 ─────────────
   *
   * La objecion se planteo dos veces y el la reafirmo por escrito, asumiendo el
   * riesgo: "yo me hago responsable si algun cliente alega". Es su tienda y es
   * su llamada, asi que queda anotado aca y no se vuelve a discutir.
   *
   * PRECIO 20 px, ADVERTENCIA 14 px. Se llego ahi en cinco pasos el mismo dia
   * —24/11,5 roto · 20/20 legal · 20/18 · 22/14 · 20/14— porque cada version
   * que cumplia se veia mal en la pagina y Piero la fue ajustando mirandola. Su
   * posicion, textual: "prefiero asumir la responsabilidad si es que algun
   * cliente llega a alegar que tener la pagina asi de fea por miedo a eso".
   *
   * LO QUE ESTO SIGNIFICA, sin adornos: la comparacion de tamanos que pide el
   * decreto NO se cumple, y el respaldo para no aceptar devoluciones queda
   * apoyado enteramente en que la advertencia sea "destacada" — que lo es, y
   * por eso lo que sigue NO es decorativo y no hay que tocarlo a la ligera:
   *
   *   - Tinta plena, 13,58:1 de contraste, no el malva apagado de la letra
   *     chica. A 14 px este es el unico canal que queda.
   *   - Pegada al boton de compra, dentro del pie.
   *   - Mas grande que la letra chica de al lado (14 contra 11,5), que es lo
   *     que la distingue de una nota al pie cualquiera.
   *
   * Volver a cumplir la letra del decreto es UN numero: igualar este token a
   * --sc-price-size. Nada mas en el codigo asume que sean distintos.
   */
  --sc-price-size: 1.25rem;
  --sc-price-weight: 700;
  --sc-disclosure-size: 0.875rem;

  --sc-gap: clamp(1.5rem, 3vw, 2.75rem);
  /* Aparte del gap entre columnas: la pagina anfitriona ya pone su propio
     aire arriba y abajo, y duplicarlo empuja el boton de compra fuera de
     pantalla en un portatil. */
  --sc-pad-block: clamp(0.75rem, 1.4vw, 1.25rem);

  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: var(--sc-gap);
  align-items: start;

  font-family: var(--sc-sans);
  color: var(--sc-ink);
  background: var(--sc-paper);
  padding: var(--sc-pad-block) var(--sc-gap);
  box-sizing: border-box;
}

.spinshop-configurator *,
.spinshop-configurator *::before,
.spinshop-configurator *::after {
  box-sizing: inherit;
}

@media (max-width: 860px) {
  .spinshop-configurator {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ------------------------------------------------------------------ stage */

.sc-stage {
  position: relative;
  /* Para que sus controles puedan reacomodarse por el ancho del ESCENARIO, que
     no es proporcional al de la ventana - ver .sc-metals. */
  container-type: inline-size;
  border-radius: var(--sc-radius-lg);
  overflow: hidden;
  /* A vignette rather than a flat fill: it puts the rings in a space instead of
     on a swatch, and the falloff hides the seam where the canvas ends. */
  background:
    radial-gradient(120% 90% at 50% 38%, var(--sc-stage-core) 0%,
      var(--sc-stage) 46%, var(--sc-stage-edge) 100%);
  aspect-ratio: 4 / 5;
  min-height: 320px;
}

@media (min-width: 861px) {
  /* Taller than square: the piece is the reason anybody is on this page, and a
     square stage next to a long panel reads as a thumbnail beside a form. */
  .sc-stage { aspect-ratio: 5 / 6; }
  /* Lo pegajoso es la COLUMNA (escenario + tira de miniaturas), no el
     escenario solo: si la tira se quedara atras al bajar, las fotos
     desaparecerian justo cuando la clienta esta leyendo el panel. */
  .sc-stagecol { position: sticky; top: 1.5rem; align-self: start; }
}

.sc-canvas {
  width: 100%;
  height: 100%;
  display: block;
}

/*
 * MIENTRAS LA TIENDA NO DICE QUE VENDE, LA PIEZA NO SE ENSEÑA.
 *
 * El eje arranca en el valor de la receta y salta al que la tienda si vende
 * cuando vuelve la consulta, asi que la cadena cambiaba sola delante de quien
 * la estaba mirando. Se oculta la pieza y su rotulo, no el escenario: el marco
 * con su degradado se queda, asi que no hay hueco ni salto de tamaño — solo una
 * pieza que aparece cuando ya es la correcta.
 *
 * Con transicion de entrada y sin transicion de salida. Aparecer suave se lee
 * como que la pieza termino de cargar; desvanecerse suave al empezar se leeria
 * como que algo se apago.
 */
.sc-awaiting-shop .sc-canvas,
.sc-awaiting-shop .sc-caption {
  opacity: 0;
  /*
   * SIN TRANSICION EN EL ESTADO OCULTO, y no es un detalle de gusto.
   *
   * Con la transicion declarada solo en la regla de abajo, corria en las DOS
   * direcciones: al entrar en espera la pieza se DESVANECIA a la vista. Se veia
   * una cadena, un fundido de salida y otra cadena entrando — o sea el cambio
   * que esto venia a evitar, ahora animado y mas largo.
   *
   * Declarandola aca en `none`, ocultar es instantaneo y solo aparecer es
   * suave. Hoy el panel ademas nace con la clase puesta, asi que no deberia
   * haber nada que ocultar; esto es la red por si alguna vez se vuelve a
   * esperar con la pieza ya en pantalla.
   */
  transition: none;
}

.sc-canvas,
.sc-caption {
  transition: opacity 0.35s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .sc-canvas,
  .sc-caption { transition: none; }
}

/*
 * Los dos grupos del pie del escenario comparten sitio y se turnan.
 *
 * Al pie hay una sola pregunta y depende del modo: viendo el par es desde qué
 * ángulo, y puesta es cuál de las dos. Puesta la vertical está clavada y el
 * giro es un vaivén, así que Perspectiva, Frente y Canto no tendrían nada que
 * hacer ahí.
 */
.sc-views,
.sc-pieces {
  position: absolute;
  left: 50%;
  bottom: 1.15rem;
  transform: translateX(-50%);
  display: flex;
  gap: 1px;
  padding: 1px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.09);
  backdrop-filter: blur(8px);
}

.sc-pieces,
.spinshop-configurator.is-worn .sc-views { display: none; }

.spinshop-configurator.is-worn .sc-pieces { display: flex; }

/* Sin par no hay nada que elegir, y el grupo queda vacío. */
.sc-pieces:empty { display: none !important; }

.sc-views button,
.sc-pieces button {
  appearance: none;
  border: 0;
  cursor: pointer;
  background: transparent;
  color: rgba(255, 255, 255, 0.62);
  font: inherit;
  font-size: 0.7rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  padding: 0.5rem 0.95rem;
  border-radius: 999px;
  transition: color 0.25s, background 0.25s;
}

.sc-views button:hover,
.sc-pieces button:hover { color: #fff; }

.sc-views button.is-on,
.sc-pieces button.is-on {
  background: rgba(255, 255, 255, 0.92);
  color: var(--sc-ink);
}

/* ----------------------------------------------------------------- metales */

/*
 * El metal es un punto dentro del escenario, abajo a la izquierda.
 *
 * Va DENTRO y no en el panel de campos porque es lo único de la ficha que se
 * juzga mirando: cambiar de metal no cambia un dato, cambia la pieza. Elegirlo
 * pegado a la joya deja el ojo donde está el efecto.
 *
 * Un punto y no una fila de botones porque en la mayoría de las tiendas habrá
 * un solo metal, y un control desplegado para una opción es ruido. Con menos de
 * dos ni se dibuja.
 *
 * Sube en vez de bajar porque se apoya en el borde inferior del escenario.
 */
.sc-metals {
  position: absolute;
  left: 1.35rem;
  /*
   * Centrado contra la pastilla de vistas, que comparte esa franja: la pastilla
   * va a 1,15rem del borde y mide 2,28rem; el punto mide 1,6rem, así que sube
   * la mitad de la diferencia. Si cambia el relleno de la pastilla, este número
   * la sigue - y se nota de inmediato porque quedan descuadrados.
   */
  bottom: calc(1.15rem + (2.28rem - 1.6rem) / 2);
  line-height: 0;
  z-index: 2;
}

/*
 * En un escenario angosto no caben lado a lado -la pastilla sola mide 275px- así
 * que el punto se sube por encima de ella. Se pregunta por el escenario y no por
 * la ventana porque no son proporcionales: apilado, el escenario es MÁS ancho a
 * 860px de ventana que a 1024.
 */
@container (max-width: 430px) {
  .sc-metals { bottom: calc(1.15rem + 2.28rem + 0.5rem); }
}

.sc-metal-list {
  position: absolute;
  bottom: calc(100% + 0.5rem);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  padding: 0.35rem;
  border-radius: 999px;
  /* La misma vestimenta que los otros controles del escenario: vidrio oscuro,
     no papel. Un panel blanco acá dentro se lee como algo pegado encima. */
  background: rgba(255, 255, 255, 0.09);
  backdrop-filter: blur(8px);
}

/*
 * OBLIGATORIO, y no es redundante: el atributo `hidden` del HTML es un
 * `display: none` de la hoja del navegador, así que el `display: flex` de
 * arriba le gana por especificidad y la lista se queda abierta para siempre.
 */
.sc-metal-list[hidden] { display: none; }

.sc-metal-toggle,
.sc-metals .sc-dot {
  appearance: none;
  cursor: pointer;
  display: block;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.28);
  /*
   * Un disco plano se lee como pintura. El brillo desplazado lo convierte en
   * una esfera de ese metal, que es lo que un swatch de material tiene que
   * parecer - y es la diferencia entre "amarillo" y "oro".
   */
  background:
    radial-gradient(circle at 32% 28%,
      #fff 0%, var(--sc-swatch, #ccc) 46%, rgba(0, 0, 0, 0.3) 130%),
    var(--sc-swatch, #ccc);
  transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
}

.sc-metal-toggle:hover,
.sc-metals .sc-dot:hover { transform: scale(1.12); }

.sc-metals.is-open .sc-metal-toggle { border-color: rgba(255, 255, 255, 0.75); }

/* Aro blanco separado por un hueco oscuro: sobre vidrio no se puede confiar en
   un color de fondo, así que el hueco lo hace el offset y no un relleno. */
.sc-metals .sc-dot.is-on {
  border-color: transparent;
  outline: 2px solid rgba(255, 255, 255, 0.92);
  outline-offset: 2px;
}

.sc-metal-toggle:focus-visible,
.sc-metals .sc-dot:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

.sc-caption {
  position: absolute;
  top: 1.15rem;
  left: 1.35rem;
  margin: 0;
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42);
}

/* ------------------------------------------------------------------ panel */

.sc-panel {
  display: flex;
  flex-direction: column;
  gap: 1.15rem;
  min-width: 0;
}

.sc-head { display: grid; gap: 0.3rem; }

.sc-eyebrow {
  margin: 0;
  font-size: 0.68rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sc-accent);
}

/*
 * Todos los nombres apilados en la misma celda: los invisibles no se ven pero sí
 * miden, así que la caja siempre tiene el alto del más largo y el panel no salta
 * al cambiar de modelo.
 *
 * "Media caña bordes con líneas" ocupa dos renglones y "Arenado" uno, y ese
 * salto corría 54 px todo lo de abajo — incluido el botón que ibas a apretar.
 * Un `min-height` fijo no serviría: cuántos renglones ocupa cada nombre depende
 * del ancho del panel, que lo decide la tienda que lo hospeda.
 */
.sc-title {
  margin: 0;
  display: grid;
  align-items: start;
  font-family: var(--sc-serif);
  font-size: var(--sc-display-size);
  font-weight: var(--sc-display-weight);
  line-height: 1.05;
  letter-spacing: var(--sc-display-spacing);
}

.sc-title > * { grid-area: 1 / 1; }

/* `visibility` y no `opacity`: así tampoco lo lee un lector de pantalla. */
.sc-title-ghost { visibility: hidden; }

/*
 * El precio va bajo el título y sobre el peso, en ese orden a propósito: el peso
 * es la EXPLICACIÓN del precio, así que leerlos seguidos cuenta por qué una
 * banda de 5 mm cuesta más que una de 2.
 */
.sc-head-money {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-top: 0.3rem;
}

.sc-price {
  margin: 0;
  font-family: var(--sc-serif);
  /* Ver `--sc-price-size`: el mismo token lo lee `.sc-disclosure`. */
  font-size: var(--sc-price-size);
  font-weight: var(--sc-price-weight);
  letter-spacing: var(--sc-display-spacing);
  /*
   * DOS COSAS DISTINTAS, Y LA SEGUNDA ES LA QUE HACIA VERSE MAL LA ADVERTENCIA.
   *
   * `tabular-nums`: los digitos ocupan lo mismo. El precio cambia con cada clic
   * de talla, y con ancho variable el numero entero se sacude.
   *
   * `lining-nums`: las cifras van a ALTURA DE MAYUSCULA. Cormorant -la display
   * de UNE- usa cifras de estilo antiguo por defecto, que corren a altura de x
   * y se hunden bajo la linea de base. O sea que a IGUAL font-size el precio se
   * ve bastante mas chico que un texto de letras, y al poner la advertencia
   * legal a su mismo tamano parecia el doble de grande.
   *
   * Piero lo dijo mirando: "el numero en esta fuente se ve mas pequeno que la
   * letra". Es literal, y el tema de UNE ya lo habia resuelto asi en el medidor
   * de tallas -- ver `.une-talla__resultado strong` en su style.css.
   *
   * Esto es lo que arregla el desbalance SIN tocar el tamano de la advertencia,
   * que es lo unico que la ley no deja bajar.
   */
  font-variant-numeric: tabular-nums lining-nums;
}

.sc-weight {
  margin: 0;
  font-size: 0.83rem;
  color: var(--sc-ink-soft);
  font-variant-numeric: tabular-nums;
}

/*
 * `hidden` GANA SIEMPRE, DENTRO DE TODO EL CONFIGURADOR.
 *
 * El atributo `hidden` del HTML es un `display: none` de la hoja del navegador,
 * asi que cualquier regla de autor que declare `display` le gana por
 * especificidad y el elemento se queda visible. Ya habia mordido dos veces —la
 * lista de metales, y de ahi salen las reglas sueltas `.sc-read[hidden]`,
 * `.sc-note[hidden]` y compania— y volvio a morder una tercera con `.sc-field`:
 * la receta de cadenas no ofrece elegir cantidad, la seccion nacia con
 * `hidden`, y el rotulo CANTIDAD se imprimia igual con nada debajo.
 *
 * Se arregla de raiz y no con un cuarto parche. La regla vale para cualquier
 * elemento del configurador, presente o futuro, asi que la proxima seccion que
 * nazca oculta no necesita acordarse de nada.
 */
.spinshop-configurator [hidden] { display: none; }

.sc-field { display: grid; gap: 0.5rem; }

.sc-label {
  margin: 0;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sc-ink-faint);
}

/* ----------------------------------------------------------------- models */

/*
 * Tres por fila, fijo, y no `auto-fit`.
 *
 * Con auto-fit el número de columnas lo decide el ancho disponible, y con seis
 * modelos eso caía en cuatro arriba y dos abajo: una fila corta y descolgada que
 * se lee como si faltara algo. Tres y tres reparten parejo y dejan la rejilla
 * cerrada.
 *
 * A dos columnas por debajo de 420 px, que es donde tres nombres como "Media
 * caña bordes con líneas" ya no caben sin partirse en cuatro renglones.
 */
.sc-models {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.5rem;
}

@media (max-width: 420px) {
  .sc-models {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.sc-model {
  appearance: none;
  cursor: pointer;
  display: grid;
  gap: 0.45rem;
  justify-items: center;
  padding: 0.5rem 0.35rem 0.45rem;
  background: transparent;
  border: 1px solid var(--sc-line);
  border-radius: var(--sc-radius);
  font: inherit;
  color: var(--sc-ink-soft);
  transition: border-color 0.25s, color 0.25s, background 0.25s;
}

.sc-model:hover { border-color: var(--sc-ink-faint); background: var(--sc-paper-warm); }

.sc-model.is-on {
  border-color: var(--sc-ink);
  color: var(--sc-ink);
  background: var(--sc-paper-warm);
}

.sc-profile { display: block; width: 34px; }
.sc-profile svg { width: 100%; height: auto; display: block; }

.sc-profile path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linejoin: round;
  stroke-linecap: round;
  /* The section is drawn open at the bottom - it is a band seen end-on, and the
     inner wall is where the finger goes, not part of the metal. */
  opacity: 0.85;
}

.sc-model.is-on .sc-profile path { opacity: 1; }

.sc-model-name {
  font-size: 0.68rem;
  line-height: 1.25;
  text-align: center;
  letter-spacing: 0.01em;
}

/* ----------------------------------------------------------------- widths */

.sc-widths,
.sc-quantity { display: flex; flex-wrap: wrap; gap: 0.4rem; }

/*
 * El grupo guarda su lugar mientras la tienda dice que largos vende.
 *
 * Los botones no se pintan hasta que vuelve la consulta —antes se mostraban los
 * de la receta y se recortaban solos—, y sin una altura reservada la ficha
 * entera salta un renglon cuando aparecen. La medida es la de un boton: 0,55rem
 * de relleno arriba y abajo, la linea de texto y el borde.
 */
.sc-widths.is-waiting { min-height: 2.6rem; }

.sc-widths button,
.sc-quantity button {
  appearance: none;
  cursor: pointer;
  min-width: 3.4rem;
  padding: 0.55rem 0.7rem;
  background: transparent;
  border: 1px solid var(--sc-line);
  border-radius: var(--sc-radius);
  font: inherit;
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
  color: var(--sc-ink-soft);
  transition: border-color 0.25s, color 0.25s, background 0.25s;
}

.sc-widths button span {
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  margin-left: 0.15rem;
  color: var(--sc-ink-faint);
}

.sc-widths button:hover,
.sc-quantity button:hover { border-color: var(--sc-ink-faint); }

.sc-quantity button { min-width: 0; }

.sc-widths button.is-on,
.sc-quantity button.is-on {
  border-color: var(--sc-ink);
  color: var(--sc-ink);
  background: var(--sc-paper-warm);
}


/* El stock del eje. Ver `syncOption()`: tres estados, no dos.

   `a pedido` se atenúa pero se puede elegir — una tienda con `backorders:
   notify` lo vende igual, y esconderlo sería mentir por omisión sobre algo que
   sí está a la venta. `agotado` se apaga entero, porque apretarlo solo lleva a
   un error al final. */
.sc-widths button.is-to-order { opacity: 0.72; }

.sc-widths button.is-to-order::after {
  content: '·';
  margin-left: 0.3em;
  opacity: 0.7;
}

.sc-widths button.is-out {
  opacity: 0.38;
  cursor: not-allowed;
  text-decoration: line-through;
}

/* ------------------------------------------------------------------ rings */

.sc-rings { display: grid; gap: 1.1rem; }

/*
 * El par va en dos columnas cuando el panel da el ancho.
 *
 * Se pregunta por el ANCHO DEL PANEL y no por el de la pantalla, porque este
 * plugin cae dentro del layout de una tienda que no conocemos: la misma ventana
 * puede darle media pantalla en un tema y una columna angosta en otro. Una
 * media query acertaría en un caso y erraría en el otro.
 *
 * Un navegador sin container queries se queda en una columna, que es como
 * estaba y se lee bien.
 */
.sc-panel { container-type: inline-size; }

/*
 * 400 px es el piso medido, no un número redondo: el stepper de talla mide
 * ~120 px fijos, así que una columna aguanta desde ~180 px y dos más la
 * canaleta caen justo ahí. Por debajo el stepper empuja y la tarjeta se
 * desborda en vez de envolver.
 */
@container (min-width: 400px) {
  .sc-rings.is-pair {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 1.25rem;
  }

  /* En columnas la línea divisoria de arriba separa las dos tarjetas entre sí
     y no una de otra, así que sobra el aire extra. */
  .sc-rings.is-pair .sc-ring { padding-top: 1.1rem; }
}

.sc-ring {
  display: grid;
  gap: 0.6rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--sc-line);
}

.sc-ring-name {
  margin: 0;
  font-family: var(--sc-serif);
  font-size: 1.15rem;
  font-weight: var(--sc-display-weight);
  letter-spacing: var(--sc-display-spacing);
}

.sc-row { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.sc-row--stack { display: grid; gap: 0.45rem; }

.sc-sub {
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sc-ink-faint);
  margin-right: auto;
}

.sc-optional {
  letter-spacing: 0.06em;
  text-transform: none;
  font-size: 0.72rem;
  color: var(--sc-ink-faint);
  opacity: 0.75;
}

.sc-row--stack .sc-sub { margin-right: 0; }

/* ---------------------------------------------------------------- stepper */

.sc-stepper {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--sc-line);
  border-radius: var(--sc-radius);
  background: #fff;
}

.sc-step {
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  width: 2.3rem;
  height: 2.5rem;
  font-size: 1.05rem;
  line-height: 1;
  color: var(--sc-ink-soft);
  transition: color 0.2s, background 0.2s;
}

.sc-step:hover { color: var(--sc-ink); background: var(--sc-paper-warm); }

.sc-size {
  width: 2.9rem;
  border: 0;
  border-left: 1px solid var(--sc-line);
  border-right: 1px solid var(--sc-line);
  background: transparent;
  text-align: center;
  font: inherit;
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  color: var(--sc-ink);
  padding: 0.62rem 0;
}

.sc-size:focus { outline: 2px solid var(--sc-accent); outline-offset: -2px; }

.sc-mm {
  font-size: 0.76rem;
  color: var(--sc-ink-faint);
  font-variant-numeric: tabular-nums;
}

.sc-mm.is-warn { color: var(--sc-warn); }

/* -------------------------------------------------------------- engraving */

.sc-text {
  width: 100%;
  padding: 0.72rem 0.85rem;
  border: 1px solid var(--sc-line);
  border-radius: var(--sc-radius);
  background: #fff;
  font: inherit;
  font-size: 0.95rem;
  color: var(--sc-ink);
  letter-spacing: 0.04em;
  transition: border-color 0.25s;
}

/* Shown uppercase because that is what the workshop's type wheel can cut. The
   conversion itself lives in machines.js; forcing the value here would fight
   the caret mid-word.

   BEHIND A CLASS since 2026-08-11, because it is the MACHINE's rule and not the
   field's: the manual engraver has one alphabet and it is capitals, while the
   M20 has real fonts and real lowercase. A medal typed in forced capitals would
   be showing a limit that does not apply to it. The shell sets the class from
   `machineRules().uppercase`. */
.spinshop-configurator.sc-uppercase .sc-text {
  text-transform: uppercase;
}

/*
 * El texto de ejemplo, más apagado que el resto de lo apagado.
 *
 * Comparte token con las medidas (`--sc-ink-faint`), y ahí estaba el problema:
 * "17.2 mm de diámetro" es un DATO y "Un nombre, una fecha" es una sugerencia
 * de qué escribir. Al mismo tono, el campo vacío se lee como un campo lleno.
 *
 * Con opacidad y no con otro color, para que una tienda que retinte sus tokens
 * se lo lleve puesto en vez de quedarse con un gris que ya no combina.
 */
.sc-text::placeholder {
  text-transform: none;
  letter-spacing: 0.01em;
  color: var(--sc-ink-faint);
  opacity: 0.55;
}

.sc-text:focus { outline: 0; border-color: var(--sc-accent); }

.sc-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  min-height: 1.25rem;
}

.sc-count {
  font-size: 0.73rem;
  color: var(--sc-ink-faint);
  font-variant-numeric: tabular-nums;
}

.sc-count.is-over { color: var(--sc-warn); }

.sc-read {
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 0;
  font: inherit;
  font-size: 0.73rem;
  letter-spacing: 0.05em;
  color: var(--sc-accent);
  border-bottom: 1px solid currentColor;
  transition: opacity 0.2s;
}

.sc-read:hover { opacity: 0.65; }
.sc-read[hidden] { display: none; }

/* ------------------------------------------------------------------- foot */

.sc-foot {
  display: grid;
  gap: 0.55rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--sc-line);
}

.sc-cta {
  appearance: none;
  cursor: pointer;
  border: 0;
  border-radius: var(--sc-radius-cta);
  padding: 0.85rem 1.5rem;
  /* La marca, no la tinta. Este boton es el hermano del CTA de la portada de
     la tienda, asi que tiene que salir del mismo token que ese; pintado con
     --sc-ink se lee casi negro al lado de un boton de marca. */
  background: var(--sc-accent);
  color: var(--sc-paper);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  transition: background 0.25s;
}

.sc-cta:hover { background: var(--sc-accent-hover); }

/*
 * LA ADVERTENCIA LEGAL, SEPARADA DE LA LETRA CHICA.
 *
 * Hasta el 2026-08-19 iban las dos en `.sc-note`: "Se confecciona a medida"
 * -que es informativo- y "no admite cambio ni devolucion" -que es lo que
 * sostiene que unas argollas grabadas no se devuelvan-. Mezcladas, la segunda
 * heredaba el tamano de la primera: 11,5 px contra 24 del precio, medido en
 * produccion.
 *
 * Separarlas es lo que permite que la advertencia sea corta y grande sin
 * convertir el pie en un ladrillo: solo esta necesita el tamano.
 *
 * TRES COSAS LA HACEN "DESTACADA", que es mas que el tamano:
 *   - El TAMANO sale de `--sc-disclosure-size`, que arranco siendo el mismo
 *     token que el precio y dejo de serlo — ver ahi, tiene dueno y fecha.
 *   - El COLOR es la tinta principal y no `--sc-ink-faint`. Con el token
 *     apagado, en el tema de UNE, quedaba en un malva de bajo contraste.
 *
 * VA DEBAJO DEL BOTON, junto a la letra chica, dentro de `.sc-fineprint`.
 * Estuvo arriba unas horas y Piero la vio en produccion: a tamano de precio y
 * suelta, partia el pie en tres bloques y empujaba el boton de compra. Cumple
 * igual — el decreto pide avisar ANTES DEL PAGO, y el pago ocurre en el
 * checkout, dos pantallas mas alla.
 */
/*
 * Las dos leidas como UN bloque, no como dos avisos sueltos.
 *
 * El gap es menor que el del pie a proposito: separadas por el ritmo del
 * `.sc-foot`, la letra chica quedaba flotando abajo sin pertenecer a nada.
 */
.sc-fineprint {
  display: grid;
  gap: 0.3rem;
}

.sc-fineprint[hidden] { display: none; }

.sc-disclosure {
  margin: 0;
  /* Ver `--sc-disclosure-size`: ya NO es el mismo token que el precio, y ese
     cambio tiene dueno y fecha. */
  font-size: var(--sc-disclosure-size);
  font-weight: 400;
  /* Interlineado de texto corrido: se aprieto a 1,3 cuando iba a 18-20 px, que
     a ese tamano evitaba que dos renglones cortos se leyeran como dos frases
     sueltas. A 14 px el problema es el contrario — apretado se vuelve un
     bloque denso y se lee peor que la letra chica que tiene al lado. */
  line-height: 1.45;
  color: var(--sc-ink);
}

.sc-disclosure[hidden] { display: none; }

.sc-note {
  margin: 0;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--sc-ink-faint);
}

/* Vacia no puede ocupar una fila del `grid` del pie: la medalla no tiene letra
   chica y quedaba una franja de aire sobre el boton. */
.sc-note[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .spinshop-configurator * { transition: none !important; }
}

/* Errors land in the note under the button, where the shopper is already
   looking. An alert() would take them out of the page they are deciding on. */
.sc-note.is-error {
  color: var(--sc-warn);
  font-weight: 600;
  /*
   * DECISION, NO EFECTO LATERAL de que la advertencia haya crecido.
   *
   * Los errores del carrito siguen viviendo en `.sc-note`, que no crecio: crecio
   * `.sc-disclosure`, que es otro elemento. Pero un "no se pudo agregar" a
   * 11,5 px apagados es demasiado discreto para lo unico que hay entre la
   * clienta y su compra, asi que sube a la escala del peso y toma el color de
   * aviso.
   *
   * No sube a `--sc-price-size`: un error no es una advertencia legal y no
   * tiene por que competir con el precio.
   */
  font-size: 0.83rem;
}

/*
 * La letra chica del peso, DEBAJO DEL PRECIO Y EL PESO.
 *
 * Estuvo al pie del panel y se movió acá el 2026-08-14: la aclaración pertenece
 * al número que aclara, y al pie quedaba a media pantalla de distancia — quien
 * dudaba del peso no iba a encontrarla, y quien llegaba al pie ya no se
 * acordaba de qué hablaba.
 *
 * Más chica y más apagada que `.sc-note`, que es donde aparecen los errores del
 * carrito: esto no reclama atención, está ahí para el que va a buscarla. El
 * ancho tope la mantiene en dos renglones cortos en vez de cruzar el panel
 * entero, que es lo que la haría parecer una advertencia.
 *
 * Y el atributo `hidden` necesita su regla explícita — la hoja del navegador
 * pierde por especificidad contra cualquier `display` propio, que es el mismo
 * error que ya costó una vuelta con la lista de metales.
 */
.sc-weight-note {
  margin: 0.15rem 0 0;
  max-width: 42ch;
  font-size: 0.68rem;
  line-height: 1.45;
  color: var(--sc-ink-faint);
  opacity: 0.85;
}

.sc-weight-note[hidden] {
  display: none;
}


/* ------------------------------------------------------------ modo puesta */

/*
 * El botón de modo va arriba a la derecha del escenario y NO junto a
 * Perspectiva / Frente / Canto. Esos tres son ángulos de cámara; esto es otra
 * escena. Juntarlos haría que un mismo grupo de controles significara dos cosas.
 */
.sc-worn {
  position: absolute;
  top: 0.9rem;
  right: 0.9rem;
  z-index: 2;
  appearance: none;
  cursor: pointer;
  padding: 0.5rem 0.95rem;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(6px);
  color: #fff;
  font: inherit;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
}

.sc-worn:hover { background: rgba(255, 255, 255, 0.18); }

.sc-worn[aria-pressed="true"] {
  background: #fff;
  color: var(--sc-stage-edge, #0b0c0f);
  border-color: #fff;
}

.sc-worn:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/*
 * La argolla que se está editando.
 *
 * La misma que marcan los botones del pie del escenario, a propósito: acá dice
 * cuál estás editando y allá cuál estás viendo, y son la misma. Es discreta
 * fuera del modo puesta, donde solo informa; ahí dentro decide qué mano se ve.
 */
.sc-ring.is-active {
  border-color: var(--sc-accent, #1c1c1e);
}

.spinshop-configurator.is-worn .sc-ring:not(.is-active) { opacity: 0.55; }


/* ==================================================================
   Tira de miniaturas bajo el escenario (2026-09-02)
   ================================================================== */

.sc-stagecol { min-width: 0; }

/* La foto ocupa el escenario entero, en el lugar del canvas. */
.sc-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: none;
}
.spinshop-configurator.is-photo .sc-photo { display: block; }

/* Con una foto en escena no hay angulos, ni dedo, ni metal que elegir. El
   canvas se esconde con visibility y no con display para que conserve su
   tamano y el visor no tenga que remedirse al volver. */
.spinshop-configurator.is-photo .sc-canvas { visibility: hidden; }
.spinshop-configurator.is-photo .sc-views,
.spinshop-configurator.is-photo .sc-pieces,
.spinshop-configurator.is-photo .sc-worn,
.spinshop-configurator.is-photo .sc-metals,
.spinshop-configurator.is-photo .sc-caption { display: none; }

.sc-media {
  display: flex;
  gap: 0.6rem;
  margin-top: 0.9rem;
  overflow-x: auto;
  scrollbar-width: none;
}
.sc-media::-webkit-scrollbar { display: none; }

.sc-thumb {
  position: relative;
  flex: 0 0 auto;
  width: 72px;
  height: 72px;
  padding: 0;
  appearance: none;
  cursor: pointer;
  overflow: hidden;
  border: 2px solid transparent;
  border-radius: var(--sc-radius);
  background: var(--sc-paper-warm);
  transition: border-color 0.2s, opacity 0.2s;
  opacity: 0.78;
}
.sc-thumb:hover { opacity: 1; }
.sc-thumb.is-on {
  opacity: 1;
  border-color: var(--sc-accent);
}
.sc-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* La marca del 3D, abajo a la izquierda de su miniatura. */
.sc-thumb-3d {
  position: absolute;
  left: 4px;
  bottom: 4px;
  padding: 1px 5px;
  border-radius: 999px;
  background: var(--sc-stage-edge, #0b0c0f);
  color: #fff;
  font: inherit;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  line-height: 1.5;
}

@media (max-width: 860px) {
  .sc-thumb { width: 60px; height: 60px; }
}

/* ==================================================================
   Fundido entre escenas (par <-> mano) y ficha del 3D en la tira
   ================================================================== */

/* El canvas se apaga mientras cambia la escena; la transicion de opacidad
   que ya tiene el canvas (0.35 s) hace el resto. Sube por sobre
   .sc-awaiting-shop, que tambien lo apaga, y con la misma regla. */
.spinshop-configurator.is-swapping .sc-canvas { opacity: 0; transition-duration: 0.19s; }

/* La ficha del 3D: el ciruela del escenario con el perfil del modelo. */
.sc-thumb--3d {
  background:
    radial-gradient(120% 90% at 50% 38%, var(--sc-stage-core) 0%,
      var(--sc-stage) 46%, var(--sc-stage-edge) 100%);
  color: #fff;
  display: grid;
  place-items: center;
}
.sc-thumb-cubo { display: block; width: 44%; opacity: 0.92; }
.sc-thumb-cubo svg { width: 100%; height: auto; display: block; }
.sc-thumb-cubo path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Pieza sin talla ni grabado: nada que elegir, nada que mostrar. Ver
   `_buildItems()` — el nodo existe para no dejar huecos en `this.cards`. */
.sc-ring--vacia { display: none; }
