/* Reseller Express — sistema visual del ÁREA PRIVADA.
 *
 * Comparte los tokens del sitio público (public/css/site.css) pero es una copia
 * física independiente, servida por el engine desde /static/reseller-app/. Esa
 * separación es deliberada: el webroot público vive en otra release, y si el
 * CSS privado dependiera de él, una activación desincronizada dejaría el
 * dashboard sin estilos.
 *
 * Nada aquí puede vivir inline: la CSP del área privada es `style-src 'self'`.
 */

/* ── Tipografía ──────────────────────────────────────────────────────────
 * Inter servido por el mismo mount, no desde /fonts/ del webroot público,
 * por la misma razón de independencia entre releases. */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("/static/reseller-app/inter-latin-400.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("/static/reseller-app/inter-latin-500.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("/static/reseller-app/inter-latin-600.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("/static/reseller-app/inter-latin-700.woff2") format("woff2");
}

:root {
  --rx-bg: #05070f;
  --rx-surface: #0b0f1f;
  --rx-surface-elevated: #131a33;
  --rx-text: #f2f4fc;
  --rx-text-muted: #9aa4c7;
  --rx-primary: #22c3f5;
  --rx-primary-hover: #5bd4ff;
  --rx-primary-ink: #04121a;
  --rx-border: rgba(255, 255, 255, 0.09);
  --rx-border-strong: rgba(255, 255, 255, 0.16);
  --rx-focus: #ffb703;
  --rx-radius-sm: 8px;
  --rx-radius-md: 16px;
  --rx-radius-lg: 24px;
  --rx-shadow: 0 30px 80px -32px rgba(0, 0, 0, 0.6);
  --rx-glow: 0 0 0 1px rgba(34, 195, 245, 0.30), 0 10px 30px -10px rgba(34, 195, 245, 0.55);
  --rx-glow-strong: 0 0 0 1px rgba(34, 195, 245, 0.55), 0 16px 44px -10px rgba(34, 195, 245, 0.80);
  --rx-danger: #ff9492;
  --rx-danger-bg: rgba(248, 81, 73, 0.12);
  --rx-danger-border: rgba(248, 81, 73, 0.38);
  --rx-success: #7ee787;
  --rx-warning: #f0c674;
  /* Completa el trío que `danger` ya tenía. Los valores NO son inventados:
     son exactamente los que `.rx-badge--wait` viene usando desde antes
     (base saturada rgba(210,153,34) al .16 de fondo y .38 de borde), que es
     la receta de estado documentada — texto saturado sobre su propio fondo,
     con su propio borde. Se extraen a tokens para que un aviso nuevo no
     vuelva a copiar los rgba a mano y se desvíe. */
  --rx-warning-bg: rgba(210, 153, 34, 0.16);
  --rx-warning-border: rgba(210, 153, 34, 0.38);
  --rx-shell-w: 232px;
  /* Alias heredados: el marcado y el JS existentes los siguen usando. */
  --rx-muted: var(--rx-text-muted);
  --rx-accent: var(--rx-primary);
  --rx-accent-dark: var(--rx-primary-hover);
  --rx-radius: var(--rx-radius-md);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  background: var(--rx-bg);
  color: var(--rx-text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  background-image:
    radial-gradient(900px 480px at 12% -8%, rgba(34, 195, 245, 0.10), transparent 60%),
    radial-gradient(760px 420px at 105% 0%, rgba(91, 212, 255, 0.07), transparent 60%);
  background-attachment: fixed;
}

a { color: var(--rx-primary); }
a:hover { color: var(--rx-primary-hover); }
img { max-width: 100%; display: block; }

:focus-visible { outline: 3px solid var(--rx-focus); outline-offset: 2px; }

.rx-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.rx-skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--rx-primary); color: var(--rx-primary-ink);
  padding: 12px 20px; border-radius: 0 0 var(--rx-radius-sm) 0; font-weight: 600;
}
.rx-skip-link:focus { left: 0; }

/* ══════════════════════════════════════════════════ APP SHELL ══════════ */
/* Móvil primero: barra superior. A partir de 1024 px se convierte en una
   sidebar fija, que es donde una navegación permanente aporta de verdad. */

.rx-shell { min-height: 100vh; }

.rx-topbar {
  position: sticky; top: 0; z-index: 100;
  background: rgba(5, 7, 15, 0.88);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--rx-border);
}
.rx-topbar-inner {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 18px; max-width: 1180px; margin: 0 auto;
}

.rx-logo {
  display: inline-flex; align-items: center; gap: 10px;
  text-decoration: none; color: var(--rx-text);
  /* (2026-08-09, "logo roto en dashboard móvil") El topbar es un flex row y
     `.rx-nav` empuja con `margin-left:auto` + `overflow-x:auto`. Sin
     `flex-shrink: 0`, cuando el nav necesita ancho, el navegador encoge el
     logo — y como `img { max-width:100% }` (regla global) limita el icono
     al ancho del contenedor ya encogido, el logo colapsaba a una línea
     vertical en móvil.

     (2026-08-14, A2) Aquel `flex-shrink: 0` se queda CORTO de matices y era
     la causa de que el header se saliera del viewport. La fila del topbar es
     `nowrap` y sus cuatro hijos en flujo eran inflexibles, así que a 320, 360
     y 430 pedían más ancho del que había y el último —el menú de usuario— se
     salía por la derecha: +26.8, +11.4 y +7.6 px medidos.

     Lo que aquel arreglo protegía —que el ICONO no se deforme— ya no depende
     de esto: se resolvió en `.rx-logo-mark` con `max-width: none` + `flex:
     none`. Así que la marca puede ceder ancho sin que el icono se toque: el
     que encoge es el wordmark, y lo hace recortándose, nunca deformándose.

     Es elástica la MARCA; los controles críticos (menú, EN/ES, avatar) siguen
     con `flex: none` y no encogen nunca. */
  flex: 0 1 auto;
  /* Sin esto un flex item no baja de su ancho de contenido y el recorte del
     wordmark no llegaría a ocurrir. */
  min-width: 0;
}
.rx-logo:hover { color: var(--rx-text); }
/* Ícono oficial (2026-08-06) -- antes era un div con gradiente + texto
   "RX". Grande a propósito (48px, más que los 34px del placeholder):
   es la única marca visible en pantallas angostas, donde .rx-logo-text
   se oculta (ver media query abajo).
   `max-width: none` (2026-08-09): la regla global `img { max-width:100% }`
   limitaba el icono al ancho del contenedor flex encogido, deformándolo.
   El icono conserva su 48×48 y aspect ratio siempre. */
.rx-logo-mark { width: 48px; height: 48px; max-width: none; flex: none; border-radius: 12px; display: block; }
.rx-logo-text {
  font-weight: 650; letter-spacing: -0.015em; font-size: 0.98rem;
  /* (2026-08-09) el wordmark jamás se envuelve letra por letra: si no
     cabe, se recorta antes que deformar el logo (el icono sigue siendo
     la marca visible en <400px, donde el texto se oculta). */
  white-space: nowrap;
  /* (2026-08-14, A2) Y ahora ese recorte ocurre de verdad: es la pieza
     elástica del header. Sin `min-width: 0` el texto impondría su ancho de
     contenido y volvería a empujar al menú de usuario fuera de pantalla. */
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
/* Wordmark "Reseller.Express": "Reseller" hereda el blanco de .rx-logo,
   ".Express" en el azul de marca. */
.rx-word-express { color: var(--rx-primary); }
/* Las media queries del header (marca compacta y extrema) viven AL FINAL
   del archivo, después de las reglas base — ver sección
   "RESPONSIVE — HEADER (móvil)" al pie. El orden importa: una regla base
   declarada después de la media query gana por igual especificidad. */

.rx-nav { display: flex; align-items: center; gap: 4px; margin-left: auto; overflow-x: auto; }
.rx-nav a {
  color: var(--rx-text-muted); text-decoration: none; font-size: 0.88rem;
  font-weight: 500; padding: 7px 11px; border-radius: 999px; white-space: nowrap;
  transition: color .18s ease, background-color .18s ease;
}
.rx-nav a:hover { color: var(--rx-text); background: rgba(255, 255, 255, 0.06); }
.rx-nav a[aria-current="page"] { color: var(--rx-text); background: rgba(255, 255, 255, 0.06); }

/* Separador entre el bloque de flujo diario (Inicio/Capturar/Mis artículos/
   Exportaciones) y el de configuración (Marketplaces/Ajustes/Ayuda). En
   móvil la barra es una fila horizontal con scroll — ahí el separador se
   dibuja vertical; en la sidebar de escritorio, horizontal. */
.rx-nav-divider {
  flex: none; align-self: stretch; width: 1px; margin: 6px 6px;
  background: var(--rx-border);
}

/* Contador junto a «Mis artículos» — lo rellena dashboard.js con el mismo
   dato que ya calcula para las tarjetas de resumen; en las demás páginas
   queda `hidden` (nunca se muestra un número inventado o desactualizado). */
.rx-nav-badge {
  display: inline-block; min-width: 20px; text-align: center;
  font-size: .7rem; font-weight: 700; padding: 1px 7px; border-radius: 999px;
  background: rgba(34, 195, 245, 0.14); color: var(--rx-primary);
  border: 1px solid rgba(34, 195, 245, 0.30);
  font-variant-numeric: tabular-nums; vertical-align: 1px;
}
.rx-nav-badge[hidden] { display: none; }

/* Solo lo ve el owner: el servidor no emite este enlace para nadie más. Se
   distingue del resto de la navegación por color para que quede claro que
   sale del área de usuario hacia una superficie interna -- SIN borde: un
   borde permanente es la única caja visible entre los enlaces del nav (el
   indicador real de página activa, `[aria-current="page"]`, solo usa fondo,
   nunca borde), así que se leía como "pestaña activa" en cualquier vista,
   sin relación con qué sección estuviera abierta de verdad. */
.rx-nav a.rx-nav-owner {
  color: var(--rx-accent);
}
.rx-nav a.rx-nav-owner:hover {
  color: var(--rx-accent); background: rgba(34, 195, 245, 0.12);
}

/* ══════════════════════════════════════════════ SELECTOR DE IDIOMA ════ */
/* Mismo componente visual que el sitio público (site.css .rx-lang-switch),
   mismos nombres de clase y atributo data-lang-switch -- app-assets/i18n.js
   lo activa solo. Vive antes del menú de usuario, no dentro de él: cambiar
   de idioma no debería requerir abrir un menú. */
.rx-lang-switch {
  display: flex;
  gap: 2px;
  border: 1px solid var(--rx-border-strong);
  border-radius: 999px;
  padding: 3px;
  flex: none;
  margin-left: 8px;
}
.rx-lang-switch button {
  border: none;
  background: none;
  padding: 6px 12px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--rx-text-muted);
  border-radius: 999px;
  cursor: pointer;
}
.rx-lang-switch button.is-active { background: var(--rx-text); color: var(--rx-bg); }

/* ══════════════════════════════════════════════ MENÚ DE USUARIO ═══════ */
/* Único punto de acceso a Perfil/Ajustes/Soporte/Cerrar sesión — vive junto
   al resto del topbar (misma sección de shell) porque comparte su mismo
   comportamiento responsive: horizontal empujado a la derecha en móvil,
   empujado al fondo de la sidebar vertical desde 1024px. */
.rx-user-menu { position: relative; margin-left: 8px; flex: none; }
.rx-user-menu-trigger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0; border: none; border-radius: 50%;
  cursor: pointer; background: transparent;
}
.rx-user-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%; overflow: hidden;
  font-size: .82rem; font-weight: 700; color: var(--rx-primary-ink);
  background: linear-gradient(140deg, var(--rx-primary-hover), var(--rx-primary));
  border: 1px solid var(--rx-border-strong);
}
.rx-user-avatar img { width: 100%; height: 100%; object-fit: cover; }
.rx-user-menu-trigger:hover .rx-user-avatar { box-shadow: 0 0 0 3px rgba(34, 195, 245, .20); }

.rx-user-menu-dropdown {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 150;
  width: 240px; padding: 8px;
  background: var(--rx-surface-elevated); border: 1px solid var(--rx-border-strong);
  border-radius: var(--rx-radius-md); box-shadow: var(--rx-shadow), 0 0 0 1px rgba(34, 195, 245, .10);
}
.rx-user-menu-dropdown[hidden] { display: none; }
.rx-user-menu-identity {
  padding: 10px 12px 12px; margin-bottom: 4px; border-bottom: 1px solid var(--rx-border);
  display: flex; flex-direction: column; gap: 2px;
}
.rx-user-menu-name { font-weight: 650; font-size: .92rem; letter-spacing: -.01em; }
.rx-user-menu-email { font-size: .8rem; color: var(--rx-text-muted); word-break: break-all; }
.rx-user-menu-item {
  display: flex; align-items: center; width: 100%; text-align: left; box-sizing: border-box;
  padding: 10px 12px; border-radius: var(--rx-radius-sm); border: none;
  background: transparent; color: var(--rx-text); font-size: .88rem; font-weight: 500;
  font-family: inherit; cursor: pointer; text-decoration: none;
}
.rx-user-menu-item:hover { background: rgba(255, 255, 255, .06); color: var(--rx-text); }
.rx-user-menu-logout {
  color: var(--rx-danger); margin-top: 4px; border-top: 1px solid var(--rx-border);
  border-radius: 0 0 var(--rx-radius-sm) var(--rx-radius-sm); padding-top: 12px;
}
.rx-user-menu-logout:hover { background: var(--rx-danger-bg); color: var(--rx-danger); }

@media (min-width: 1024px) {
  .rx-user-menu { margin-left: 0; margin-top: auto; }
  .rx-user-menu-dropdown { top: auto; bottom: 4px; left: calc(100% + 10px); right: auto; }
}

.rx-shell-main { max-width: 1180px; margin: 0 auto; padding: 26px 18px 64px; }

@media (min-width: 1024px) {
  .rx-topbar { position: fixed; inset: 0 auto 0 0; width: var(--rx-shell-w); border-bottom: none; border-right: 1px solid var(--rx-border); }
  .rx-topbar-inner { flex-direction: column; align-items: stretch; gap: 26px; padding: 24px 18px; height: 100%; }
  .rx-nav { flex-direction: column; align-items: stretch; margin-left: 0; gap: 2px; overflow: visible; }
  .rx-nav a { padding: 9px 12px; border-radius: var(--rx-radius-sm); font-size: 0.9rem; }
  /* En la sidebar vertical el separador de bloques pasa a línea horizontal. */
  .rx-nav-divider { width: auto; height: 1px; align-self: auto; margin: 10px 4px; }
  .rx-shell-main { margin-left: var(--rx-shell-w); max-width: none; padding: 40px 40px 80px; }
  .rx-shell-inner { max-width: 1080px; }
}

/* ══════════════════════════════════════════════════ BOTONES ═══════════ */
.rx-btn {
  position: relative; overflow: hidden; isolation: isolate;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1px solid transparent; border-radius: 999px;
  padding: 12px 24px; font-size: 0.94rem; font-family: inherit; font-weight: 600;
  cursor: pointer; background: var(--rx-primary); color: var(--rx-primary-ink);
  text-decoration: none; box-shadow: var(--rx-glow);
  transition: background-color .18s ease, box-shadow .18s ease, transform .18s ease,
              color .18s ease, border-color .18s ease;
}
.rx-btn::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,.55) 50%, transparent 70%);
  transform: translateX(-120%);
}
.rx-btn:hover { background: var(--rx-primary-hover); color: var(--rx-primary-ink); box-shadow: var(--rx-glow-strong); transform: translateY(-1px); }
.rx-btn:hover::after { animation: rx-sheen .75s ease; }
.rx-btn:active { transform: translateY(1px); box-shadow: var(--rx-glow); }
@keyframes rx-sheen { to { transform: translateX(120%); } }
/* (Audit A3, 2026-08-26) Antes: `opacity: .45` sobre el botón entero.
   Sobre un fondo oscuro, desvanecer texto Y fondo A LA VEZ los acerca al
   MISMO color de respaldo -- el par que partía de 9.21:1 (AAA) caía a
   2.73:1 medido, por debajo incluso del piso de texto grande (3:1). Reponer
   opacidad no lo arregla: hay que dejar de desvanecer los dos lados a la
   vez. En su lugar, un tratamiento plano e intencional: mismo texto
   apagado que ya usan etiquetas y navegación en reposo (`--rx-text-muted`
   sobre superficie oscura, 7.72:1 verificado -- ver auditoría), un lavado
   translúcido en vez del cian, sin sombra ni glow. No inventa un color: es
   el mismo par ya usado en el resto del sistema, aplicado aquí. */
.rx-btn[disabled] {
  opacity: 1; background: rgba(255, 255, 255, .05); color: var(--rx-text-muted);
  border-color: var(--rx-border); box-shadow: none; transform: none; cursor: not-allowed;
}
/* Ícono de marca dentro de un botón (2026-08-06) -- .rx-btn ya trae
   `gap: 8px` en su flex, así que solo hace falta redondear la esquina. */
.rx-btn-icon { border-radius: 5px; flex: none; }
/* (Audit A3) Antes: forzaba `background: var(--rx-primary)` en hover --
   deuda ya documentada ("el hover deshabilitado del shell fuerza el fondo
   primario"), y con mayor especificidad que `.rx-btn-secondary:hover`,
   pisaba TAMBIÉN el fondo transparente de los botones secundarios
   deshabilitados dejando su propio texto casi ilegible encima de un cian
   lavado. Un control deshabilitado no reacciona: en reposo o en hover es
   el mismo objeto inerte. */
.rx-btn[disabled]:hover {
  background: rgba(255, 255, 255, .05); color: var(--rx-text-muted);
  border-color: var(--rx-border); box-shadow: none; transform: none;
}
.rx-btn[disabled]:hover::after { animation: none; }

.rx-btn-secondary {
  background: transparent; border-color: var(--rx-border-strong); color: var(--rx-text); box-shadow: none;
}
.rx-btn-secondary:hover {
  background: rgba(34,195,245,.08); border-color: var(--rx-primary);
  color: var(--rx-primary); box-shadow: 0 0 0 1px rgba(34,195,245,.22);
}
.rx-btn-secondary:hover::after { animation: none; }
.rx-btn-lg { padding: 15px 30px; font-size: 1rem; }

.rx-btn-danger {
  background: transparent; border-color: var(--rx-danger-border); color: var(--rx-danger); box-shadow: none;
}
.rx-btn-danger:hover {
  background: var(--rx-danger-bg); border-color: var(--rx-danger); color: var(--rx-danger); box-shadow: none;
}
.rx-btn-danger:hover::after { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .rx-btn, .rx-btn:hover, .rx-btn:active { transition: none; transform: none; }
  .rx-btn::after { display: none; }
}

/* ══════════════════════════════════════════ CONTROLES DE FORMULARIO ═══ */
/* Bloque crítico: el detalle genera 16 inputs, 2 selects y 3 textareas. Sin
   estas reglas se dibujan con el blanco por defecto del navegador sobre navy,
   que es ilegible. Se estilizan por ELEMENTO, no solo por clase, para cubrir
   también los controles que el JavaScript crea sin envolver en .rx-field. */
.rx-field { margin-bottom: 16px; display: flex; flex-direction: column; gap: 7px; }
/* Marcador de campo obligatorio (Beta Draft readiness, 2026-08-13) -- ver
   dashboard.js field(): distingue los campos del perfil de exportación sin
   valor por defecto seguro (país del vendedor/de envío) de sus vecinos, que
   sí lo tienen. */
.rx-field-required { color: var(--rx-danger); font-weight: 600; }
/* El `display: flex` de arriba gana sobre el `display: none` implícito del
   atributo nativo `hidden` (misma cascada, declarado después) -- sección de
   cuenta (2026-08-06): el campo de "contraseña actual" se ocultaba con
   `hidden` pero seguía viéndose. Sin esto, CUALQUIER `.rx-field` oculto con
   `hidden` en el futuro tendría el mismo defecto. */
.rx-field[hidden] { display: none; }
.rx-field label,
.rx-label {
  font-size: .8rem; font-weight: 600; color: var(--rx-text-muted); letter-spacing: .02em;
}

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="search"], input[type="url"], input[type="tel"], input[type="date"],
input:not([type]), select, textarea {
  width: 100%;
  padding: 11px 13px;
  border-radius: var(--rx-radius-sm);
  border: 1px solid var(--rx-border);
  background: rgba(5, 7, 15, .65);
  color: var(--rx-text);
  font-size: .94rem;
  font-family: inherit;
  line-height: 1.5;
  transition: border-color .18s ease, box-shadow .18s ease;
}
textarea { min-height: 92px; resize: vertical; }
select {
  /* Flecha propia: el indicador nativo se dibuja oscuro sobre oscuro. */
  appearance: none; -webkit-appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--rx-text-muted) 50%),
    linear-gradient(135deg, var(--rx-text-muted) 50%, transparent 50%);
  background-position: calc(100% - 18px) 52%, calc(100% - 13px) 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 34px;
}
select option { background: var(--rx-surface-elevated); color: var(--rx-text); }

/* (Audit A5, 2026-08-26) 55% medía 3.11:1 sobre el hueco excavado del campo
   -- por debajo del piso normal de AA (4.5:1), aunque pasaba el de texto
   grande. 75% mide 4.88:1 verificado (AA con margen) y sigue siendo
   claramente `--rx-text-muted`, un color distinto de `--rx-text` (el que
   usa un valor ya escrito) -- no un mismo tono más oscuro, así que un
   placeholder nunca se lee como respuesta ya dada. */
input::placeholder, textarea::placeholder { color: rgba(154, 164, 199, .75); }

/* El navegador fuerza su propio fondo (normalmente blanco) sobre un campo
   autocompletado e ignora `background-color` directo -- el truco estándar
   es un `box-shadow` inset del mismo color que ya usan estos inputs, con
   una transición larga para que nunca se vea el fondo nativo ni un
   parpadeo al aplicarse. */
input:-webkit-autofill, input:-webkit-autofill:hover,
input:-webkit-autofill:focus, input:-webkit-autofill:active {
  -webkit-box-shadow: 0 0 0 1000px rgba(5, 7, 15, .65) inset;
  -webkit-text-fill-color: var(--rx-text);
  caret-color: var(--rx-text);
  transition: background-color 5000s ease-in-out 0s;
}

input:focus, select:focus, textarea:focus {
  border-color: var(--rx-primary);
  box-shadow: 0 0 0 3px rgba(34, 195, 245, .16);
  outline: none;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--rx-focus); outline-offset: 2px;
}
input[disabled], select[disabled], textarea[disabled] {
  opacity: .5; cursor: not-allowed; background: rgba(255, 255, 255, .04);
}
input[type="checkbox"], input[type="radio"] { width: auto; accent-color: var(--rx-primary); }

fieldset { border: 1px solid var(--rx-border); border-radius: var(--rx-radius-md); padding: 16px; margin: 0 0 16px; }
legend { font-size: .8rem; font-weight: 600; color: var(--rx-text-muted); padding: 0 6px; }

/* ══════════════════════════════════════════════════ TARJETAS ══════════ */
.rx-card {
  background: var(--rx-surface); border: 1px solid var(--rx-border);
  border-radius: var(--rx-radius-md); padding: 22px; box-shadow: var(--rx-shadow);
}
@media (min-width: 720px) { .rx-card { padding: 26px; } }

/* (v2A, 2026-08-11) La barra superior es `position: sticky`, así que flota
   sobre el contenido en cuanto la página se desplaza. `.rx-section` ya se
   protegía con `scroll-margin-top`, pero era la ÚNICA que lo hacía: los
   títulos del asistente del detalle de producto no lo tenían y quedaban 36 px
   POR DEBAJO de la barra en cualquier `scrollIntoView()` o navegación por
   ancla — medido a 360x800, 390x844 y 430x932, en inglés y en español.

   Se arregla en el contenedor de scroll con `scroll-padding-top`, que cubre
   de una vez TODO destino de desplazamiento (anclas, `scrollIntoView`,
   foco por teclado) en vez de ir persiguiendo selector por selector. La
   barra mide 73-77 px según el ancho; 92 px deja aire y respeta el notch. */
html {
  scroll-padding-top: calc(92px + env(safe-area-inset-top));
}
@media (min-width: 1024px) {
  /* A partir de aquí la barra es una columna lateral: no tapa nada. */
  html { scroll-padding-top: 24px; }
}

.rx-section { margin-top: 40px; scroll-margin-top: 84px; }
@media (min-width: 1024px) { .rx-section { scroll-margin-top: 24px; } }
.rx-section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; margin-bottom: 16px; flex-wrap: wrap; }
.rx-section-title { font-size: 1.05rem; font-weight: 650; letter-spacing: -.015em; margin: 0; }
.rx-section-sub { color: var(--rx-text-muted); font-size: .88rem; margin: 0; }

.rx-eyebrow {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--rx-text-muted); font-weight: 600; margin: 0 0 12px;
}

/* ══════════════════════════════════════════════════ BIENVENIDA ════════ */
.rx-hero { margin-bottom: 8px; }
.rx-hero h1 {
  margin: 0; font-size: clamp(1.6rem, 4.4vw, 2.35rem); font-weight: 700;
  letter-spacing: -.028em; line-height: 1.14; max-width: 22ch; text-wrap: balance;
}
.rx-hero-lead { margin: 14px 0 0; color: var(--rx-text-muted); font-size: 1rem; max-width: 58ch; }
.rx-hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }

/* ══════════════════════════════════════════════════ RECORRIDO ═════════ */
.rx-flow { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; grid-template-columns: 1fr; }
@media (min-width: 720px) { .rx-flow { grid-template-columns: repeat(4, 1fr); gap: 14px; } }
.rx-flow-step {
  display: flex; align-items: flex-start; gap: 12px; position: relative;
  background: var(--rx-surface); border: 1px solid var(--rx-border);
  border-radius: var(--rx-radius-md); padding: 15px 16px;
}
.rx-flow-num {
  width: 25px; height: 25px; flex: none; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .76rem; font-weight: 700; color: var(--rx-primary);
  background: rgba(34,195,245,.12); border: 1px solid rgba(34,195,245,.35);
}
.rx-flow-body { display: flex; flex-direction: column; gap: 2px; }
.rx-flow-body b { font-size: .92rem; font-weight: 650; letter-spacing: -.01em; }
.rx-flow-body span { font-size: .83rem; color: var(--rx-text-muted); }
@media (min-width: 720px) {
  .rx-flow-step + .rx-flow-step::before {
    content: ""; position: absolute; left: -10px; top: 50%; width: 6px; height: 6px;
    border-top: 1.5px solid var(--rx-border-strong); border-right: 1.5px solid var(--rx-border-strong);
    transform: translateY(-50%) rotate(45deg);
  }
}

/* ══════════════════════════════════════════════════ CONTADORES ════════ */
.rx-summary { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.rx-summary .rx-card:first-child { grid-column: 1 / -1; }
@media (min-width: 700px) {
  .rx-summary { grid-template-columns: repeat(5, 1fr); gap: 12px; }
  .rx-summary .rx-card:first-child { grid-column: auto; }
}
.rx-summary .rx-card {
  padding: 14px 16px; text-align: left; box-shadow: none;
  transition: border-color .18s ease, background-color .18s ease;
}
.rx-summary .rx-card:hover { border-color: var(--rx-border-strong); background: var(--rx-surface-elevated); }
/* (Phase 2, 2026-09-01; Phase 5 lo extiende a "Listo para vender") Tiles
   pulsables del resumen -- `role="button" tabindex="0"` sobre un `<div>`
   (nunca un `<button>`: `.rx-card` no lleva reset de botón nativo).
   `[aria-pressed="true"]` marca el filtro activo con el mismo tratamiento
   sólido ya usado para otros controles "encendidos" en esta página (ver
   rx-journey-suggestion-cta). */
#rx-summary-needs-you, #rx-summary-ready-to-sell { cursor: pointer; }
#rx-summary-needs-you:focus-visible, #rx-summary-ready-to-sell:focus-visible {
  outline: 2px solid var(--rx-focus); outline-offset: 2px;
}
#rx-summary-needs-you[aria-pressed="true"], #rx-summary-ready-to-sell[aria-pressed="true"] {
  border-color: var(--rx-primary); background: var(--rx-surface-elevated);
}
.rx-num {
  font-size: 1.55rem; font-weight: 700; display: block; line-height: 1.05;
  color: var(--rx-primary); letter-spacing: -.025em; font-variant-numeric: tabular-nums;
}
.rx-label {
  font-size: .69rem; color: var(--rx-text-muted); margin-top: 5px; display: block;
  text-transform: uppercase; letter-spacing: .06em; font-weight: 500; line-height: 1.35;
}

/* ══════════════════════════════════════════ CUADRÍCULA DE PRODUCTOS ═══ */
/* Sustituye la lista de texto: en un producto photo-first, la fotografía es
   el identificador que el vendedor reconoce, no el título. */
.rx-list { display: grid; grid-template-columns: 1fr; gap: 14px; }
@media (min-width: 620px) { .rx-list { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .rx-list { grid-template-columns: repeat(3, 1fr); } }

/* La tarjeta se estiliza sobre la estructura que el JavaScript emite:
 *   .rx-item > .rx-item-media + .rx-item-body(.rx-item-title + .rx-item-meta) + span.rx-badge + a
 * `.rx-item-meta` ya trae la próxima acción real (rxNextStepLabel), así que no
 * hace falta inventar ningún campo. `.rx-item-media` pide los medios del
 * producto aparte y pinta la primera foto; sin fotos la caja queda vacía —
 * nunca finge tener una imagen que no existe. */
.rx-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  overflow: hidden; padding: 17px 18px 18px;
  background: var(--rx-surface); border: 1px solid var(--rx-border);
  border-radius: var(--rx-radius-md); text-decoration: none; color: inherit;
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.rx-item:hover {
  border-color: rgba(34,195,245,.35); transform: translateY(-2px);
  box-shadow: var(--rx-shadow), 0 0 0 1px rgba(34,195,245,.12);
}
.rx-item-body { display: flex; flex-direction: column; gap: 6px; }
.rx-item-media {
  aspect-ratio: 4 / 3; width: 100%; background: var(--rx-surface-elevated);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  border: 1px solid var(--rx-border); border-radius: var(--rx-radius-sm);
}
.rx-item-media img { width: 100%; height: 100%; object-fit: cover; }
.rx-item-title { font-weight: 650; letter-spacing: -.01em; line-height: 1.35; font-size: 1rem; }
.rx-item-meta { color: var(--rx-text-muted); font-size: .84rem; }
/* El enlace «Abrir» del JS pasa a ser la acción visible de la tarjeta. */
.rx-item > a {
  margin-top: auto; font-size: .86rem; font-weight: 600;
  color: var(--rx-primary); text-decoration: none;
}
.rx-item > a:hover { color: var(--rx-primary-hover); text-decoration: underline; }

.rx-badge {
  display: inline-block; padding: 4px 11px; border-radius: 999px;
  font-size: .72rem; font-weight: 600; letter-spacing: .01em;
  background: rgba(255,255,255,.06); color: var(--rx-text); border: 1px solid var(--rx-border);
}
.rx-badge--ok { background: rgba(46,160,67,.16); color: var(--rx-success); border-color: rgba(46,160,67,.38); }
.rx-badge--wait { background: rgba(210,153,34,.16); color: var(--rx-warning); border-color: rgba(210,153,34,.38); }
.rx-badge--draft { background: rgba(56,139,253,.16); color: var(--rx-primary); border-color: rgba(56,139,253,.38); }
/* (2026-09-02) El badge de borrador real es un `<button>`, no un `<span>`:
   sin esto hereda la tipografia y el cursor por defecto del navegador y
   deja de parecer el mismo pill que el resto de badges. El foco NO se
   redefine aqui: el anillo global de 3px ambar ya cubre cualquier boton. */
.rx-badge--link { font: inherit; cursor: pointer; }
.rx-badge--link:hover { filter: brightness(1.15); }
/* (2026-09-02) `display: contents` saca el envoltorio del arbol de layout:
   el boton dentro sigue siendo hijo DIRECTO del flex de `.rx-item-body`,
   igual que antes de envolverlo -- sin esto `align-self`/`width: fit-content`
   del badge dejarian de aplicar (solo actuan sobre hijos flex directos). */
.rx-item-badge-group { display: contents; }
.rx-item-badge-caption { display: block; margin-top: 2px; text-align: right; }

.rx-progress { height: 4px; border-radius: 999px; background: rgba(255,255,255,.08); overflow: hidden; }
.rx-progress > span { display: block; height: 100%; background: linear-gradient(90deg, var(--rx-primary), var(--rx-primary-hover)); }

/* ══════════════════════════════════════════════════ ESTADO VACÍO ══════ */
.rx-empty {
  text-align: center; padding: 56px 24px 52px;
  background:
    radial-gradient(520px 200px at 50% 0%, rgba(34,195,245,.09), transparent 70%),
    var(--rx-surface);
  border: 1px dashed var(--rx-border-strong); border-radius: var(--rx-radius-lg);
}
@media (min-width: 720px) { .rx-empty { padding: 76px 32px 68px; } }
.rx-empty::before {
  content: ""; display: block; width: 56px; height: 56px; margin: 0 auto 22px;
  border-radius: 16px; border: 1px solid rgba(34,195,245,.35);
  background: linear-gradient(rgba(34,195,245,.14), rgba(34,195,245,.05));
  box-shadow: 0 0 28px -8px rgba(34,195,245,.55);
}
.rx-empty p:first-of-type { font-size: 1.2rem; font-weight: 650; color: var(--rx-text); letter-spacing: -.015em; margin: 0 0 8px; }
.rx-empty p + p { color: var(--rx-text-muted); max-width: 48ch; margin: 0 auto 26px; font-size: .95rem; }
.rx-empty .rx-btn { margin: 0 6px 8px; }
.rx-empty-note { color: var(--rx-text-muted); font-size: .82rem; margin-top: 22px; }

.rx-error {
  text-align: center; padding: 44px 20px; color: var(--rx-danger);
  background: var(--rx-danger-bg); border: 1px solid var(--rx-danger-border);
  border-radius: var(--rx-radius-md);
}
.rx-error p { color: var(--rx-danger); }

.rx-skeleton {
  height: 190px; border-radius: var(--rx-radius-md); border: 1px solid var(--rx-border);
  background: linear-gradient(90deg, var(--rx-surface) 25%, var(--rx-surface-elevated) 37%, var(--rx-surface) 63%);
  background-size: 400% 100%; animation: rx-shimmer 1.4s ease infinite;
}
@keyframes rx-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) { .rx-skeleton { animation: none; } }

/* ══════════════════════════════════════════ DIVULGACIÓN PROGRESIVA ════ */
.rx-disclosure { border: 1px solid var(--rx-border); border-radius: var(--rx-radius-md); background: var(--rx-surface); }
.rx-disclosure > summary {
  list-style: none; cursor: pointer; padding: 18px 22px;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.rx-disclosure > summary::-webkit-details-marker { display: none; }
.rx-disclosure > summary:focus-visible { outline: 3px solid var(--rx-focus); outline-offset: -3px; }
.rx-disclosure > summary::before {
  content: ""; width: 7px; height: 7px; flex: none;
  border-right: 1.5px solid var(--rx-text-muted); border-bottom: 1.5px solid var(--rx-text-muted);
  transform: rotate(-45deg); transition: transform .2s ease;
}
.rx-disclosure[open] > summary::before { transform: rotate(45deg); }
.rx-disclosure-label { font-weight: 600; font-size: .95rem; }
.rx-disclosure-hint { color: var(--rx-text-muted); font-size: .83rem; }
.rx-disclosure-body { padding: 0 22px 22px; }
@media (prefers-reduced-motion: reduce) { .rx-disclosure > summary::before { transition: none; } }

/* ══════════════════════════════════════════════════ MODAL ═════════════ */
dialog {
  border: 1px solid var(--rx-border-strong); border-radius: var(--rx-radius-md);
  padding: 0; width: min(520px, 92vw);
  background: var(--rx-surface-elevated); color: var(--rx-text);
  box-shadow: var(--rx-shadow), 0 0 0 1px rgba(34,195,245,.10);
}
dialog::backdrop { background: rgba(3,5,12,.72); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
.rx-modal-body { padding: 26px; }
.rx-modal-body h2 { font-size: 1.2rem; letter-spacing: -.015em; margin: 0 0 20px; }
.rx-modal-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 22px; }
.rx-form-error { color: var(--rx-danger); font-size: .85rem; min-height: 1.2em; }
.rx-hint { font-size: .78rem; color: var(--rx-text-muted); }

/* ══════════════════════════════════════════════════ PIE ═══════════════ */
.rx-footer { margin-top: 52px; padding-top: 22px; border-top: 1px solid var(--rx-border); text-align: center; }
.rx-footer p { margin: 0; color: var(--rx-text-muted); font-size: .78rem; opacity: .8; }

/* ══════════════════════════════════ INSIGNIA DE eBay (2026-08-06) ══════
   Marca visual reutilizable para cualquier botón/sección que pida conexión
   con eBay o muestre datos que vienen de su API -- para que el vendedor
   identifique de un vistazo qué parte de la pantalla es "la de eBay".
   Punto de 4 colores (paleta oficial de marca) en vez de reproducir el
   wordmark completo. */
.rx-ebay-badge {
  display: inline-flex; align-items: center; gap: 6px; font-size: .78rem; font-weight: 700;
  padding: 3px 10px 3px 8px; border-radius: 999px; background: var(--rx-surface-elevated);
  border: 1px solid var(--rx-border); color: var(--rx-text); vertical-align: middle; line-height: 1.6;
}
.rx-ebay-badge-dot {
  width: 10px; height: 10px; border-radius: 50%; flex: none;
  background: conic-gradient(#e53238 0 25%, #0064d2 25% 50%, #f5af02 50% 75%, #86b817 75% 100%);
}
h2 .rx-ebay-badge, .rx-detail-section > h2 .rx-ebay-badge { margin-left: 8px; vertical-align: middle; }

/* ══════════════════════════════════════════════ RESPONSIVE — HEADER (móvil) ═══
   (2026-08-09, "mostrar nombre Reseller.Express en header privado")
   Estas media queries viven AL FINAL del archivo a propósito: el orden de
   declaración es lo único que gana frente a reglas base de igual
   especificidad (un `padding` base declarado después pisa la media query).
   La identidad completa [icono + Reseller.Express] es SIEMPRE visible;
   solo se compacta en pantallas angostas. Prioridad del header:
   1. marca, 2. Home, 3. EN/ES, 4. avatar. El nav conserva min-width:0 +
   flex:1 para scroll propio y NUNCA empuja/desborda el layout. */

/* (2026-08-14, A2) El límite era 400px y dejaba 401-439 en tierra de nadie:
   tamaño completo en un viewport demasiado estrecho. Medido: el header en
   tamaño completo pide 439.6px y en compacto 375.4px, así que por debajo de
   439.6 hay que compactar o el wordmark se trunca. A 430 daba
   "Reseller.Ex…" -- el desbordamiento ya lo resolvía la elasticidad, pero la
   marca quedaba rota. No es un breakpoint nuevo: es el límite del que ya
   existía, puesto donde dice la medición y no a ojo. */
@media (max-width: 439.98px) {
  .rx-topbar-inner { gap: 8px; padding: 10px 12px; }
  .rx-logo { gap: 6px; }
  .rx-logo-mark { width: 36px; height: 36px; border-radius: 9px; }
  .rx-logo-text { font-size: 0.78rem; letter-spacing: -0.01em; }
  .rx-nav { min-width: 0; flex: 1 1 auto; margin-left: 6px; }
  .rx-nav a { padding: 6px 8px; font-size: 0.8rem; }
  .rx-lang-switch { margin-left: 4px; }
  .rx-lang-switch button { padding: 5px 8px; font-size: 11.5px; }
  .rx-user-menu { margin-left: 4px; }
  .rx-user-avatar { width: 30px; height: 30px; }
}

/* (2026-08-14, A2) Por debajo de 375.4px el wordmark COMPLETO ya no cabe ni
   compactado -- ese es el ancho medido que necesita el header con la marca
   entera. Sin esta regla el texto se trunca y sale "Reseller.E…", que parece
   un fallo de renderizado, no una decisión.

   Se oculta el fragmento SECUNDARIO y queda "Reseller": una palabra completa,
   con el icono sosteniendo la marca. Se eligió mirando las tres alternativas
   renderizadas a 320 y 360, no razonando sobre ellas: dejar que ".Express" se
   recortara solo daba "Reseller.Exp" cortado a media letra, peor todavía
   porque ni siquiera avisa de que falta algo.

   Esto NO es el arreglo del desbordamiento -- ese es la elasticidad de
   `.rx-logo`, y funciona a cualquier ancho, con breakpoint o sin él. Esto es
   una regla tipográfica, que es para lo que sirven las media queries. */
@media (max-width: 375.98px) {
  .rx-word-express { display: none; }
}

/* Extremo angosto (320-340px): compactación máxima SIN ocultar el nombre.
   El selector EN/ES se reduce al mínimo legible pero nunca desaparece. */
@media (max-width: 340px) {
  .rx-topbar-inner { gap: 6px; padding: 10px 8px; }
  .rx-logo { gap: 5px; }
  .rx-logo-mark { width: 32px; height: 32px; border-radius: 8px; }
  .rx-logo-text { font-size: 0.72rem; }
  .rx-nav { margin-left: 4px; }
  .rx-lang-switch { padding: 2px; }
  .rx-lang-switch button { padding: 4px 6px; font-size: 11px; }
  .rx-user-avatar { width: 28px; height: 28px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Navegación móvil — cajón (UX-1/UX-5, 2026-08-11)

   El defecto: `.rx-nav` era una tira horizontal con `overflow-x: auto` y 11
   destinos. Medido a 360/390/430 px, solo 4 eran alcanzables y no había
   ninguna señal de que se pudiera deslizar; seis secciones quedaban fuera.

   Debajo de 1024 px la barra pasa a ser un cajón con disparador propio.
   Desde 1024 px NO cambia nada: la columna lateral fija ya funcionaba, así
   que este bloque entero se desactiva ahí abajo.
   ══════════════════════════════════════════════════════════════════════════ */

.rx-nav-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex: none; margin-left: auto;
  border: 1px solid var(--rx-border-strong); border-radius: 12px;
  background: transparent; color: var(--rx-text); cursor: pointer;
  transition: background-color .18s ease, border-color .18s ease;
}
.rx-nav-toggle:hover { background: rgba(255, 255, 255, 0.06); }
.rx-nav-toggle:focus-visible { outline: 2px solid var(--rx-primary); outline-offset: 2px; }
/* Icono dibujado, no un glifo de texto: tres trazos que se cruzan al abrir. */
.rx-nav-toggle-bars { position: relative; display: block; width: 18px; height: 12px; }
.rx-nav-toggle-bars::before,
.rx-nav-toggle-bars::after,
.rx-nav-toggle-bars span {
  content: ""; position: absolute; left: 0; width: 100%; height: 2px;
  border-radius: 2px; background: currentColor;
  transition: transform .22s cubic-bezier(.22, 1, .36, 1), opacity .14s ease;
}
.rx-nav-toggle-bars::before { top: 0; }
.rx-nav-toggle-bars span { top: 5px; }
.rx-nav-toggle-bars::after { top: 10px; }
[data-rx-nav-open] .rx-nav-toggle-bars::before { transform: translateY(5px) rotate(45deg); }
[data-rx-nav-open] .rx-nav-toggle-bars span { opacity: 0; }
[data-rx-nav-open] .rx-nav-toggle-bars::after { transform: translateY(-5px) rotate(-45deg); }

.rx-nav-backdrop {
  position: fixed; inset: 0; z-index: 140; border: 0; padding: 0;
  background: rgba(3, 5, 12, 0.62);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  opacity: 0; pointer-events: none; transition: opacity .22s ease;
}

@media (max-width: 1023.98px) {
  /* El cajón cerrado vive en `translateX(100%)`, es decir FUERA del borde
     derecho, y un elemento `fixed` desplazado sigue contando para
     `scrollWidth`: sin esto aparece scroll horizontal en toda la app.
     `clip` y no `hidden` a propósito — `hidden` convertiría el elemento en
     contenedor de scroll y rompería el `position: sticky` de la barra. */
  html { overflow-x: clip; }

  /* `backdrop-filter` convierte a la barra en BLOQUE CONTENEDOR de sus
     descendientes `position: fixed` (igual que `transform` o `filter`), así
     que el cajón se quedaba encerrado dentro del alto del header en vez de
     ocupar la pantalla. Se retira solo en móvil —donde existe el cajón— y
     el fondo pasa a ser opaco: a simple vista es el mismo cristal oscuro. */
  .rx-topbar {
    backdrop-filter: none; -webkit-backdrop-filter: none;
    background: rgba(5, 7, 15, 0.97);
  }

  .rx-nav-toggle { display: inline-flex; }

  .rx-nav {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 150;
    width: min(310px, 86vw);
    display: flex; flex-direction: column; align-items: stretch;
    gap: 2px; margin-left: 0; overflow-y: auto; overflow-x: hidden;
    padding: 76px 14px calc(18px + env(safe-area-inset-bottom));
    background: var(--rx-surface, #0a0e1a);
    border-left: 1px solid var(--rx-border);
    box-shadow: -22px 0 48px rgba(0, 0, 0, .48);
    transform: translateX(100%);
    transition: transform .26s cubic-bezier(.22, 1, .36, 1);
    visibility: hidden;
  }
  /* Objetivo táctil real: 44 px de alto, no 32. */
  .rx-nav a {
    display: flex; align-items: center; min-height: 44px;
    padding: 10px 14px; font-size: 0.98rem; border-radius: 12px;
    white-space: normal;
  }
  .rx-nav-divider {
    width: auto; height: 1px; align-self: auto; margin: 8px 12px;
  }

  [data-rx-nav-open] .rx-nav { transform: translateX(0); visibility: visible; }
  [data-rx-nav-open] .rx-nav-backdrop { opacity: 1; pointer-events: auto; }
  /* Bloquea el fondo mientras el cajón está abierto. */
  body[data-rx-nav-open] { overflow: hidden; }
}

@media (min-width: 1024px) {
  /* Escritorio intacto: sin disparador y sin telón. */
  .rx-nav-toggle, .rx-nav-backdrop { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .rx-nav, .rx-nav-backdrop,
  .rx-nav-toggle-bars::before, .rx-nav-toggle-bars::after, .rx-nav-toggle-bars span {
    transition: none;
  }
}

/* ── Objetivos táctiles críticos ≥44 px ──────────────────────────────────
   El conmutador de idioma medía 32×22 y el disparador del menú de usuario
   quedaba por debajo del mínimo cómodo con el pulgar. */
.rx-lang-switch button { min-width: 44px; min-height: 44px; }
.rx-user-menu-trigger { min-width: 44px; min-height: 44px; }
.rx-user-menu-item { min-height: 44px; display: flex; align-items: center; }

/* ── Volver: navegación real, no texto suelto ────────────────────────────
   `.rx-back` no tenía NI UNA regla: se renderizaba como un enlace desnudo
   que no parecía pulsable. */
.rx-back {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; padding: 8px 14px 8px 10px;
  color: var(--rx-text-muted); text-decoration: none;
  font-size: .92rem; font-weight: 500;
  border: 1px solid var(--rx-border); border-radius: 999px;
  transition: color .18s ease, background-color .18s ease, border-color .18s ease;
}
.rx-back:hover { color: var(--rx-text); background: rgba(255, 255, 255, .06); border-color: var(--rx-border-strong); }
.rx-back:focus-visible { outline: 2px solid var(--rx-primary); outline-offset: 2px; }
/* (Direction D V1) mismo defecto que .rxs-err ya tuvo: .rx-back declara su
   propio `display`, que le gana al `[hidden]` del navegador por defecto --
   sin esto, ocultarlo por JS (estado de éxito, Sección 6) no se veía. */
.rx-back[hidden] { display: none; }

/* Aviso de precio bajo costo (2026-08-31). Nace de un incidente real: un
   vendedor perdió dinero en su primera venta porque el precio de mercado no
   cubría el envío. Usa el token de advertencia que ya existe, no un color
   nuevo, y se apoya en `.rx-hint` para tipografía. */
.rx-price-floor-warning {
  margin-top: 12px; padding: 10px 12px; border-radius: 8px;
  background: var(--rx-warning-bg); border: 1px solid var(--rx-warning-border);
  color: var(--rx-text);
}

/* Economía por opción de precio (2026-08-31): envío incluido y resultado
   real. Una opción que pierde dinero se atenúa y se marca en rojo, y nunca
   recibe el resaltado de "elegida" -- resaltarla equivale a recomendarla. */
.rx-price-choice-shipping { display: block; font-size: .74rem; color: var(--rx-text-muted); }
.rx-price-choice-net { display: block; font-size: .78rem; font-weight: 600; margin-top: 2px; }
.rx-price-choice-net--gain { color: var(--rx-success); }
.rx-price-choice-net--loss { color: var(--rx-danger); }
.rx-price-choice-loss { border-color: var(--rx-danger-border); opacity: .82; }

/* ══════════════════════════════════════ SUGERENCIA DE LOTE ══════════════
   Propone vender varios artículos juntos en un solo anuncio. Nace de un
   caso real: 3 libros de ~$9 vendidos por separado pierden ~$20 (tres
   envíos), y como lote ganan (un solo envío). El envío casi no sube al
   agrupar, y esa es toda la historia que la tarjeta tiene que contar.

   DECISIONES:
   - NO es una tarjeta dentro de otra tarjeta: vive como hermana de la lista
     de artículos, no anidada. La comparación de abajo tampoco lleva cajas
     propias -- se separa con una línea de luz, no con chrome.
   - El cian NO aparece aquí salvo en el botón: la Regla de la Lámpara Única
     dice que el acento marca dónde se actúa, y aquí solo se actúa en un
     sitio. Los números usan la receta de estado (éxito/peligro).
   - Las dos columnas NO se apilan en móvil. La comparación ES el contenido;
     apilarla la destruye. Se estrechan y encogen, y siguen cabiendo a 320px.
   - La jerarquía se hace con peso y color, no con tamaño (regla del sistema). */
.rx-bundle-suggestion {
  background: var(--rx-surface); border: 1px solid var(--rx-border);
  border-radius: 16px; padding: 22px; margin-bottom: 18px;
}
.rx-bundle-suggestion h2 {
  margin: 0 0 6px; font-size: 1.4rem; font-weight: 600; line-height: 1.3; color: var(--rx-text);
}
/* Recortada a dos renglones A PROPÓSITO. Los títulos reales son largos
   ("David J. Schwartz, Ph.D. The Magic of Thinking Big Book"): cuatro de
   ellos ocupaban CINCO renglones en teléfono y empujaban la comparación
   —que es el mensaje— fuera de la primera pantalla. Aquí solo hace falta
   reconocer de qué libros habla; la lista completa está justo debajo, en
   "Mis artículos". */
.rx-bundle-members {
  margin: 0 0 18px; color: var(--rx-text-muted); font-size: .88rem; line-height: 1.6;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.rx-bundle-compare {
  display: grid; grid-template-columns: 1fr 1px 1fr; gap: 14px; align-items: start;
  padding: 14px 0; border-top: 1px solid var(--rx-border); border-bottom: 1px solid var(--rx-border);
}
.rx-bundle-compare-rule { background: var(--rx-border); align-self: stretch; }
.rx-bundle-col-label {
  display: block; font-size: .78rem; font-weight: 600; letter-spacing: .01em;
  color: var(--rx-text-muted); margin-bottom: 6px;
}
/* La línea del envío es el pivote: es lo único que de verdad cambia entre
   las dos columnas, así que se muestra con el mismo formato en ambas para
   que la diferencia salte sin explicarla. */
.rx-bundle-shipping { display: block; font-size: .84rem; color: var(--rx-text-muted); margin-bottom: 8px; }
.rx-bundle-outcome { display: block; font-size: 1rem; font-weight: 600; line-height: 1.4; }
.rx-bundle-outcome--loss { color: var(--rx-danger); }
.rx-bundle-outcome--gain { color: var(--rx-success); }
.rx-bundle-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 18px; }
/* 44x44 real de área táctil: el uso es en teléfono y el sistema eligió AAA. */
.rx-bundle-dismiss {
  background: none; border: 0; color: var(--rx-text-muted); cursor: pointer;
  font-size: .94rem; font-weight: 600; padding: 12px 14px; min-height: 44px;
  border-radius: 999px; transition: color .18s ease;
}
.rx-bundle-dismiss:hover { color: var(--rx-text); }
@media (prefers-reduced-motion: reduce) { .rx-bundle-dismiss { transition: none; } }
@media (max-width: 439.98px) {
  .rx-bundle-suggestion { padding: 18px; }
  .rx-bundle-suggestion h2 { font-size: 1.15rem; }
  .rx-bundle-compare { gap: 10px; }
  .rx-bundle-outcome { font-size: .94rem; }
}

/* ── "Pon tu propio precio" (2026-09-01) ─────────────────────────────────
   Tercera tarjeta: no es una sugerencia del sistema, es el campo donde el
   vendedor decide. Comparte la caja de las otras dos para que se lea como
   una opción más, pero nunca lleva el resalte de "recomendada": el sistema
   no recomienda un precio que no ha propuesto. */
.rx-price-custom { display: flex; flex-direction: column; gap: 8px; }
.rx-price-custom-row {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--rx-border); border-radius: var(--rx-radius-sm);
  padding: 8px 10px; background: var(--rx-bg);
}
.rx-price-custom-currency { color: var(--rx-text-muted); font-size: .9rem; }
.rx-price-custom-input {
  flex: 1; min-width: 0; border: 0; background: none; color: var(--rx-text);
  font: inherit; font-weight: 700; font-size: 1.05rem; padding: 4px 0;
  min-height: 32px;
}
.rx-price-custom-input:focus { outline: none; }
/* El anillo va en la CAJA, no en el input: así el foco se ve alrededor de
   todo el control, moneda incluida, en vez de partirlo por la mitad. */
.rx-price-custom-row:focus-within {
  outline: 3px solid var(--rx-focus); outline-offset: 2px;
  border-color: var(--rx-primary);
}
.rx-price-custom-result { margin: 0; font-size: .84rem; line-height: 1.5; min-height: 1.5em; }
/* Tres estados, tres colores. Nunca se pinta una pérdida donde hay ganancia. */
.rx-price-custom-healthy { color: var(--rx-primary); }
.rx-price-custom-thin    { color: var(--rx-warning-fg, #d29922); }
.rx-price-custom-loss    { color: var(--rx-danger); }
.rx-price-custom-unknown { color: var(--rx-text-muted); }
.rx-price-custom-save { align-self: flex-start; }
.rx-price-custom-save:disabled { opacity: .5; cursor: default; }
