/* ============================================================
   UI KIT SMARTBUY — hoja de estilos canónica
   ============================================================
   Este es el ORIGINAL. IntegraCommissions.Admin e IntegraCommissions.Cliente
   tienen cada una su propia copia de este archivo (wwwroot/css/site.css) porque
   cada app se publica sola y no comparten build ni proyecto — ver README.md
   de esta carpeta para la dinámica completa.

   Si mejoras algo visual en una app, tráelo aquí primero y luego llévalo a las
   demás. Si necesitas algo nuevo que no está aquí, agrégalo aquí también aunque
   solo lo use una app por ahora — así la próxima app que lo necesite ya lo
   encuentra listo.
   ============================================================ */

/* ============================================================
   1. Tokens — paleta de marca Smartbuy (ver CLAUDE.md raíz > Sistema de diseño)
   ============================================================ */
:root {
  --sb-azul: #174FB0;
  --sb-azul-oscuro: #123f8c;
  --sb-azul-petroleo: #005F8B;
  --sb-naranja: #FE8100;
  --sb-naranja-oscuro: #e57400;
  --sb-beige: #EDE8D0;
  --sb-marron: #664D03;
  --sb-texto: #212529;
  --sb-secundario: #888888;
  --sb-borde: #E9ECEF;
  --sb-borde-fuerte: #DDDDDD;
  --sb-fondo: #F4F6F9;
  --sb-superficie: #ffffff;

  /* Ajustables por app: el ancho del sidebar depende de qué tan largo sea el
     texto de tus enlaces de menú; el tamaño de ícono, de cuántos íconos por
     fila caben cómodos. No los cambies aquí — sobreescríbelos en el site.css
     de tu app después de copiar este archivo. */
  --sb-sidebar-ancho: 140px;
  --sb-radio: 1rem;
}

/* Tipografía: PENDIENTE — reemplazar por la fuente oficial de Smartbuy Store
   en cuanto se confirme (ver CLAUDE.md raíz). Mientras tanto, fuente de sistema. */
body {
  background-color: var(--sb-fondo);
  color: var(--sb-texto);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* ============================================================
   2. Shell — sidebar + header + contenido (usado por _Layout.cshtml)
   ============================================================ */
.sb-app {
  display: flex;
  min-height: 100vh;
}

.sb-sidebar {
  width: var(--sb-sidebar-ancho);
  /* !important: Bootstrap fuerza background-color:transparent!important en .offcanvas-lg
     a partir de 992px (para que se comporte como sidebar estático), así que sin esto
     el fondo azul desaparece en escritorio. */
  background-color: var(--sb-azul) !important;
  color: #fff;
  flex-shrink: 0;
  /* El menú va a seguir creciendo (Inicio, Registrar venta, Mis ventas,
     Vendedores, Productos, Categorías, Marcas...) — con overflow visible
     los últimos links quedarían cortados en pantallas bajas en vez de
     scrollear. overflow-y en vez de overflow: los bordes redondeados del
     link activo no deben cortarse por overflow-x. */
  overflow-y: auto;
  /* Scrollbar delgado y a tono con el sidebar azul — el scrollbar gris
     por defecto del navegador es ancho (~15-17px) y le come espacio real
     al menú (140px de ancho total); uno delgado y translúcido casi no se
     nota hasta que hace falta. scrollbar-width/color: Firefox; los
     ::-webkit-scrollbar-*: Chrome/Edge/Safari. */
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.35) transparent;
}

@media (min-width: 992px) {
  .sb-sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
  }
}

.sb-sidebar::-webkit-scrollbar {
  width: 6px;
}

.sb-sidebar::-webkit-scrollbar-track {
  background: transparent;
}

.sb-sidebar::-webkit-scrollbar-thumb {
  background-color: rgba(255, 255, 255, 0.35);
  border-radius: 999px;
}

.sb-sidebar::-webkit-scrollbar-thumb:hover {
  background-color: rgba(255, 255, 255, 0.55);
}

.sb-sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.5rem 1.25rem 0.25rem;
}

.sb-logo {
  font-weight: 700;
  font-size: 1.35rem;
  color: #fff;
}

.sb-sidebar-subtitulo {
  padding: 0 1.25rem 1rem;
  color: rgba(255, 255, 255, 0.65);
  font-size: 0.85rem;
}

.sb-nav {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 0.5rem 0.75rem;
}

.sb-nav-link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 1.1rem 0.5rem;
  border-radius: 1rem;
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
  font-size: 0.85rem;
  text-align: center;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.sb-nav-link:hover {
  background-color: rgba(255, 255, 255, 0.12);
  color: #fff;
}

.sb-nav-link.active,
.sb-nav-link.active:hover {
  background-color: var(--sb-naranja) !important;
  color: #fff !important;
  font-weight: 600;
  transition: none !important;
  animation: none !important;
}

.sb-icon {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
}

.sb-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.sb-header {
  background: var(--sb-superficie);
  border-bottom: 1px solid var(--sb-borde);
  padding: 1rem 1.5rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  position: sticky;
  top: 0;
  z-index: 10;
}

.sb-header-title {
  font-size: 1.35rem;
  margin: 0;
  color: var(--sb-texto);
  flex: 1;
}

.sb-header-usuario {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--sb-secundario);
  font-size: 0.9rem;
}

/* Botón de ícono suelto en el header (config, notificaciones). Distinto de
   .sb-avatar: este es transparente hasta hover, el avatar siempre tiene fondo. */
.sb-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--sb-secundario);
  padding: 0;
  text-decoration: none;
}

.sb-icon-btn:not(:disabled):hover {
  background-color: var(--sb-fondo);
  color: var(--sb-azul);
}

/* Deshabilitado a propósito (solo visual, ej. "próximamente"): se ve activo,
   no "gris apagado" como un <button disabled> normal — evita que parezca roto. */
.sb-icon-btn:disabled {
  opacity: 1;
  cursor: default;
}

.sb-icon-btn .sb-icon {
  width: 20px;
  height: 20px;
}

.sb-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border: none;
  border-radius: 50%;
  background-color: var(--sb-naranja);
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
  flex-shrink: 0;
}

/* Botón que envuelve el círculo + el nombre — es este botón entero el que
   abre el dropdown (data-bs-toggle), no solo el círculo, para que el
   nombre también sea parte del área clickeable. El nombre se oculta en
   pantallas muy angostas para no apretar el header (queda solo el
   círculo, igual que antes). */
.sb-usuario-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border: none;
  background: transparent;
  padding: 0.25rem 0.75rem 0.25rem 0.25rem;
  border-radius: 999px;
  cursor: pointer;
}

.sb-usuario-btn:hover,
.sb-usuario-btn:focus {
  background-color: var(--sb-fondo);
}

.sb-usuario-btn:hover .sb-avatar,
.sb-usuario-btn:focus .sb-avatar {
  background-color: var(--sb-naranja-oscuro);
}

.sb-usuario-nombre {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--sb-texto);
  white-space: nowrap;
}

/* Menú del avatar (Ver perfil / Cambiar contraseña / Cerrar sesión) */
.dropdown-menu {
  border-radius: 0.75rem;
  border-color: var(--sb-borde);
  min-width: 12rem;
}

.dropdown-header {
  font-weight: 600;
  color: var(--sb-texto);
}

.dropdown-item:active {
  background-color: var(--sb-naranja);
  color: var(--sb-marron);
}

/* Para opciones de menú "próximamente": visible pero no clickeable. */
.dropdown-item.disabled {
  pointer-events: none;
}

.sb-btn-menu {
  border: none;
  background: transparent;
  color: var(--sb-azul);
  padding: 0.25rem;
  display: inline-flex;
}

.sb-content {
  padding: 1.25rem;
  flex: 1;
}

@media (min-width: 768px) {
  .sb-content {
    padding: 1.75rem;
  }
}

/* ============================================================
   3. Tarjetas
   ============================================================ */
.card {
  border: 1px solid var(--sb-borde);
  border-radius: var(--sb-radio);
  background: var(--sb-superficie);
}

.sb-stat-card {
  padding: 1.25rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.sb-stat-valor {
  font-size: 2rem;
  font-weight: 700;
  color: var(--sb-azul);
  line-height: 1;
}

.sb-stat-etiqueta {
  color: var(--sb-secundario);
  font-size: 0.9rem;
}

/* Modificadores de color para un stat que en sí mismo es "bueno" o "malo"
   (ej. transacciones aprobadas vs. rechazadas) — mismos dos tonos que ya
   usan .badge-estado-aprobada/-rechazada, no colores nuevos. El azul de
   .sb-stat-valor sigue siendo el default para números neutros (totales,
   montos). Nunca uses fondos de color sólido en la tarjeta completa (así
   lo tenía el sandbox) — .sb-stat-card se queda blanca siempre, la que
   cambia es la cifra. */
.sb-stat-valor-exito {
  color: #0f5132;
}

.sb-stat-valor-alerta {
  color: #842029;
}

/* Tarjeta que envuelve un <canvas> de Chart.js: alto fijo para que el gráfico
   no crezca sin control (Chart.js necesita un contenedor con altura definida). */
.sb-chart-card {
  padding: 1.25rem 1.5rem;
}

.sb-chart-card h2 {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 1rem;
}

.sb-chart-contenedor {
  position: relative;
  height: 260px;
}

/* ============================================================
   4. Botones y formularios (naranja Smartbuy)
   ============================================================ */
.btn {
  border-radius: 999px;
}

.btn-primary {
  background-color: var(--sb-naranja) !important;
  border-color: var(--sb-naranja) !important;
  color: #fff !important;
  font-weight: 600;
  box-shadow: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.05s ease;
}

/* Oscurece + levanta con sombra al pasar el mouse — antes no había ningún
   cambio visual en hover (mismo color que en reposo), así que un botón
   naranja no se sentía clickeable hasta hacerle clic. */
.btn-primary:hover {
  background-color: var(--sb-naranja-oscuro) !important;
  border-color: var(--sb-naranja-oscuro) !important;
  box-shadow: 0 0.35rem 0.75rem rgba(254, 129, 0, 0.35);
}

.btn-primary:focus {
  box-shadow: 0 0 0 0.2rem rgba(254, 129, 0, 0.25) !important;
}

/* Al presionar, un poquito más oscuro todavía y sin la sombra "flotante"
   del hover — se siente hundido en vez de solo cambiar de color. */
.btn-primary:active {
  background-color: var(--sb-naranja-oscuro) !important;
  border-color: var(--sb-naranja-oscuro) !important;
  box-shadow: none !important;
  transform: translateY(1px);
}

.btn-outline-secondary {
  color: var(--sb-azul);
  border-color: var(--sb-borde-fuerte);
}

.btn-outline-secondary:hover {
  background-color: var(--sb-azul);
  border-color: var(--sb-azul);
  color: #fff;
}

.btn-outline-danger {
  border-radius: 999px;
}

.form-control,
.form-select {
  border-radius: 0.65rem;
  border-color: var(--sb-borde-fuerte);
}

.form-control:focus,
.form-select:focus {
  border-color: var(--sb-naranja);
  box-shadow: 0 0 0 0.2rem rgba(254, 129, 0, 0.25);
}

.form-label {
  font-weight: 600;
  color: var(--sb-texto);
}

/* Aviso dentro de un campo deshabilitado a propósito (funcionalidad futura,
   ej. "la subida de factura se habilita cuando exista IntegraImage"). */
.campo-deshabilitado-nota {
  background-color: var(--sb-beige);
  color: var(--sb-marron);
  border-radius: 0.65rem;
  padding: 0.75rem 1rem;
  font-size: 0.9rem;
}

/* ============================================================
   5. Paginación (estilo píldora redondeada, paleta Smartbuy)
   ============================================================ */
.page-link {
  color: var(--sb-azul);
  border-color: var(--sb-borde-fuerte);
  border-radius: 999px !important;
  margin: 0 0.15rem;
}

.page-link:hover {
  color: var(--sb-azul-oscuro);
  background-color: var(--sb-fondo);
  border-color: var(--sb-borde-fuerte);
}

.page-item.active .page-link {
  background-color: var(--sb-naranja);
  border-color: var(--sb-naranja);
  color: #fff;
}

.page-item.disabled .page-link {
  color: var(--sb-secundario);
}

/* ============================================================
   6. Badge de estado — patrón genérico para "estado de un registro"
   ============================================================
   Nace del flujo de EstadoVenta (Reportada/EnRevision/Aprobada/Rechazada),
   pero el patrón de color es reutilizable para cualquier estado con la misma
   forma: neutral-pendiente / azul-en curso / verde-aprobado / rojo-rechazado.
   Un módulo nuevo con sus propios estados puede reusar .badge-estado y sumar
   sus propias variantes -nombreDelEstado siguiendo esta misma paleta.
   ============================================================ */
.badge-estado {
  display: inline-block;
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
}

.badge-estado-reportada {
  background-color: var(--sb-beige);
  color: var(--sb-marron);
}

.badge-estado-enrevision {
  background-color: #cfe2ff;
  color: #084298;
}

.badge-estado-aprobada {
  background-color: #d1e7dd;
  color: #0f5132;
}

.badge-estado-rechazada {
  background-color: #f8d7da;
  color: #842029;
}

/* Ejemplo de variante propia (ver comentario arriba): un módulo con estado
   binario Activa/Inactiva (ej. Categorías) reusa los mismos dos colores
   que ya significan "aprobado" y "neutral/pendiente", sin inventar tono
   nuevo — así el usuario no tiene que aprender un color por módulo. */
.badge-estado-activa {
  background-color: #d1e7dd;
  color: #0f5132;
}

.badge-estado-inactiva {
  background-color: var(--sb-beige);
  color: var(--sb-marron);
}

/* Publicado/Borrador (ej. Productos): mismos dos colores otra vez — sigue
   siendo "aprobado/visible" vs "neutral/pendiente", ningún estado binario
   del kit necesita un tercer color. */
.badge-estado-publicado {
  background-color: #d1e7dd;
  color: #0f5132;
}

.badge-estado-borrador {
  background-color: var(--sb-beige);
  color: var(--sb-marron);
}

/* "Mis pedidos" (tienda pública, 2026-10-21): Estado del pago
   (Pendiente/Pagado) y Estado de la orden (Pendiente/En Proceso) son dos
   semáforos de 2-3 estados — mismo criterio que Activa/Inactiva arriba,
   alias con nombre propio sobre los mismos 3 colores ya establecidos
   (beige=neutral, azul=en curso, verde=aprobado/pagado). Ningún color
   nuevo. */
.badge-estado-pagopendiente,
.badge-estado-ordenpendiente {
  background-color: var(--sb-beige);
  color: var(--sb-marron);
}

.badge-estado-pagado {
  background-color: #d1e7dd;
  color: #0f5132;
}

.badge-estado-enproceso {
  background-color: #cfe2ff;
  color: #084298;
}

/* Etiqueta de TIPO de registro (no es un estado del flujo de vida, es una
   clasificación fija: "Producto Padre" vs "Variante"). Por eso NO reusa
   .badge-estado ni su paleta de semáforo — un tono neutro propio para no
   mezclar "tipo de dato" con "estado actual". */
.badge-tipo {
  display: inline-block;
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  background-color: var(--sb-secundario);
  color: #fff;
}

/* Etiqueta de ROL de usuario (admin/seller/client): única excepción a
   "clasificación = .badge-tipo gris", a pedido explícito del cliente —
   quiere distinguir el rol de un vistazo en el listado de Usuarios.
   Reusa los mismos 3 tonos de .badge-estado (verde/azul/beige), nunca
   colores nuevos: admin=verde (mayor privilegio), seller=azul (staff
   operativo), client=beige (cuenta de tienda, el tono "neutral"). */
.badge-rol {
  display: inline-block;
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
}

.badge-rol-admin {
  background-color: #d1e7dd;
  color: #0f5132;
}

.badge-rol-seller {
  background-color: #cfe2ff;
  color: #084298;
}

.badge-rol-client {
  background-color: var(--sb-beige);
  color: var(--sb-marron);
}

/* Etiqueta de ACCIÓN en la Bitácora de auditoría (Crear/Editar/Eliminar):
   acá sí conviene un color por verbo porque no hay una columna "Estado"
   aparte que ya avise de un problema — es la única señal para detectar un
   "Eliminar" entre muchas filas. Reusa .badge-estado (crear=aprobada,
   editar=enrevision, eliminar=rechazada). En el log de Seguridad, en
   cambio, la columna "Estado" (Éxito/Fallo) ya cumple ese rol, así que su
   columna "Acción" se queda en .badge-tipo gris para no duplicar señales. */
.badge-estado-creado {
  background-color: #d1e7dd;
  color: #0f5132;
}

.badge-estado-editado {
  background-color: #cfe2ff;
  color: #084298;
}

.badge-estado-eliminado {
  background-color: #f8d7da;
  color: #842029;
}

/* ============================================================
   7. Tablas: scroll horizontal propio, nunca desborda la página
   ============================================================ */
.sb-tabla-wrapper {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.sb-tabla-wrapper table {
  margin-bottom: 0;
}

.sb-tabla-wrapper tbody tr:hover {
  background-color: var(--sb-fondo);
}

/* Fila separadora para agrupar visualmente registros relacionados dentro
   de una misma tabla (ej. los 2 intentos SaleInitiation/SaleCompletion de
   un mismo pago, en el historial de una orden). Es una etiqueta de grupo,
   no un registro más — por eso <td colspan> a todo el ancho, fondo tenue
   y texto chico. El fondo es el mismo --sb-fondo que ya usa el hover de
   fila, no un tono nuevo. */
.sb-tabla-fila-grupo td {
  background-color: var(--sb-fondo);
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--sb-secundario);
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
}

/* Miniatura circular para la primera columna de una tabla (logo de marca,
   imagen de producto, etc.). Con <img> adentro se recorta a círculo; sin
   imagen real todavía, muestra iniciales — mismo tamaño que .sb-avatar
   pero en gris neutro, para no confundirse con el avatar de usuario
   (ese sí es naranja, este no representa una persona). */
.sb-miniatura {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background-color: var(--sb-borde);
  color: var(--sb-secundario);
  font-size: 0.7rem;
  font-weight: 700;
  flex-shrink: 0;
  overflow: hidden;
}

.sb-miniatura img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Variante cuadrada de .sb-miniatura: para fotos de producto (rectas por
   naturaleza) en vez de logos/avatares (donde el círculo ya es el estándar).
   object-fit: contain, no cover — una foto de producto normalmente tiene
   fondo blanco/transparente y no debe recortarse como un logo circular sí. */
.sb-miniatura-cuadrada {
  border-radius: 0.5rem;
}

.sb-miniatura-cuadrada img {
  object-fit: contain;
}

/* Swatch de color — para variantes de producto (Azul, Negro, etc.). El
   color en sí es un dato, no una decisión de diseño, así que se fija con
   `style="background-color:..."` en el markup, no con una clase por color;
   esta regla solo define la forma/tamaño/borde, iguales para cualquier color. */
.sb-color-swatch {
  display: inline-block;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  border: 1px solid var(--sb-borde-fuerte);
  flex-shrink: 0;
}

/* Variante clickeable de `.sb-color-swatch` — filtro "Color" del catálogo
   de la tienda pública (site.css sección 20). Checkbox oculto + anillo
   naranja con `:has()` cuando está marcado, mismo criterio de selección
   que `.sb-tarjeta-opcion` (sección 14). */
.tienda-filtro-color {
  display: inline-flex;
  padding: 2px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
}

.tienda-filtro-color:has(input:checked) {
  border-color: var(--sb-naranja);
}

.tienda-filtro-color input {
  display: none;
}

/* ============================================================
   8. Pantalla de cuenta (login / cambio de contraseña): dos columnas
   (formulario + marca), apiladas en móvil. Usada por _LayoutCuenta.cshtml.
   ============================================================ */
.sb-cuenta-body {
  background-color: var(--sb-fondo);
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.sb-cuenta-wrapper {
  width: 100%;
  max-width: 760px;
}

.sb-cuenta-card {
  display: flex;
  flex-direction: column-reverse;
  background: var(--sb-superficie);
  border-radius: var(--sb-radio);
  overflow: hidden;
  box-shadow: 0 1rem 3rem rgba(23, 79, 176, 0.15);
}

@media (min-width: 768px) {
  .sb-cuenta-card {
    flex-direction: row;
  }
}

.sb-cuenta-form {
  flex: 1;
  padding: 2.5rem 2rem;
}

.sb-cuenta-marca {
  flex: 1;
  /* background-color de respaldo si la imagen no carga; el degradado
     encima es del mismo azul (no negro) para que sea un tinte de marca,
     no un oscurecido genérico — y para que el texto blanco siga legible
     sobre cualquier parte de la foto. Ruta de la imagen relativa a este
     archivo: si copias site.css a TuModulo/wwwroot/css/site.css, la ruta
     cambia a ../img/fondo.png (site.css ya no está al lado de img/). */
  background-color: var(--sb-azul);
  background-image: linear-gradient(rgba(23, 79, 176, 0.82), rgba(23, 79, 176, 0.82)), url('img/fondo.png');
  background-size: cover;
  background-position: center;
  color: #fff;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0.75rem;
  padding: 2.5rem 2rem;
}

.sb-cuenta-marca .sb-logo {
  font-size: 1.75rem;
}

/* Logo real de Smartbuy arriba del formulario — del lado del formulario y no del panel
   de la foto, porque ese panel se oculta en móvil y el logo debe verse siempre. Chico a
   propósito: es una herramienta interna, quien entra ya conoce la marca. El margen
   negativo compensa el aire transparente que el PNG trae a la izquierda, para que el
   dibujo quede alineado con el título de abajo. */
.sb-cuenta-logo {
  display: block;
  height: 4rem;
  width: auto;
  margin: 0 0 1.25rem -0.75rem;
}

/* ============================================================
   9. Tabs — navegación por pestañas dentro de una tarjeta
   ============================================================
   Reemplaza el acordeón para formularios largos con varias secciones (ej.
   "Crear producto": info básica / precios / inventario / envío / variantes /
   publicación) — cada sección vive en su propia pestaña en vez de apilarse
   colapsada. Ver Patrones/formulario-tabs.cshtml.

   Es el componente nativo de Bootstrap (nav-tabs + tab-content, con
   data-bs-toggle="tab") — esta sección solo le pone la piel de Smartbuy
   encima, no reemplaza su JS.
   ============================================================ */
.sb-tabs {
  border-bottom: 1px solid var(--sb-borde);
  flex-wrap: nowrap;
  overflow-x: auto;
  /* Con muchas pestañas en pantalla angosta, scrollea en vez de envolver o
     apachurrar el texto — mismo criterio que .sb-tabla-wrapper con tablas. */
  -webkit-overflow-scrolling: touch;
}

.sb-tabs .nav-link {
  border: none;
  border-bottom: 3px solid transparent;
  border-radius: 0;
  padding: 0.9rem 1.25rem;
  color: var(--sb-secundario);
  font-weight: 600;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* Tamaño de ícono dentro de una pestaña — así ningún ícono de tab necesita
   style="width:...;height:..." inline; el tamaño lo decide esta regla, no
   cada instancia (ver iconos.md > "Escala de tamaños" para el resto de
   contextos: 34px por defecto en .sb-icon, 20px acá y en .sb-icon-btn). */
.sb-tabs .nav-link .sb-icon {
  width: 20px;
  height: 20px;
}

.sb-tabs .nav-link:hover {
  color: var(--sb-azul);
  border-bottom-color: var(--sb-borde-fuerte);
}

.sb-tabs .nav-link.active {
  color: var(--sb-naranja-oscuro);
  background-color: rgba(254, 129, 0, 0.08);
  border-bottom-color: var(--sb-naranja);
}

/* Numerito de paso — opcional, solo para wizards de varios pasos (una
   pestaña simple de 2-3 secciones no lo necesita). */
.sb-tab-paso {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background-color: var(--sb-borde);
  color: var(--sb-secundario);
  font-size: 0.75rem;
  font-weight: 700;
  flex-shrink: 0;
}

.sb-tabs .nav-link.active .sb-tab-paso {
  background-color: var(--sb-naranja);
  color: #fff;
}

.sb-tab-contenido {
  padding: 1.5rem 0 0.5rem;
}

/* ============================================================
   10. Checkbox / switch con el naranja de marca
   ============================================================
   Sin esto, Bootstrap pinta el estado marcado de azul — rompe la regla ya
   establecida en el resto del kit de que naranja = indicador activo/
   seleccionado (nav activo, foco de input, página activa en la
   paginación). Aplica globalmente a cualquier <input type="checkbox">
   o switch (ej. "Activa" en Categorías), no es un componente nuevo.
   ============================================================ */
.form-check-input:checked {
  background-color: var(--sb-naranja);
  border-color: var(--sb-naranja);
}

.form-check-input:focus {
  border-color: var(--sb-naranja);
  box-shadow: 0 0 0 0.2rem rgba(254, 129, 0, 0.25);
}

/* ============================================================
   11. Modales — mismo lenguaje visual que las tarjetas
   ============================================================
   Sin esto, Bootstrap le da a .modal-content su propio radio (0.5rem)
   distinto al de las tarjetas (--sb-radio, 1rem) — un modal se sentía "de
   otra pantalla" en vez de una extensión del mismo sistema. Referencia
   UX/UI para CUALQUIER modal nuevo: "Reiniciar contraseña" en Vendedores
   (modal-por-fila-en-listado.cshtml) — header con título + cerrar, body
   con el contenido/formulario, footer con Cancelar + acción a la derecha.
   ============================================================ */
.modal-content {
  border-radius: var(--sb-radio);
  border: 1px solid var(--sb-borde);
}

.modal-header {
  border-bottom: 1px solid var(--sb-borde);
  padding: 1.25rem 1.5rem;
}

.modal-title {
  font-weight: 700;
  color: var(--sb-texto);
}

.modal-body {
  padding: 1.5rem;
}

.modal-footer {
  border-top: 1px solid var(--sb-borde);
  padding: 1rem 1.5rem;
}

/* ============================================================
   12. Avatar grande — para la vista centrada de "Mi perfil"
   ============================================================
   Mismo círculo con inicial que .sb-avatar del header, pero de solo
   lectura (no es un botón, no abre nada) y más grande para ser el punto
   focal de una tarjeta centrada — ver Patrones y vista-previa > "Mi perfil".
   ============================================================ */
.sb-avatar-grande {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 5rem;
  height: 5rem;
  border-radius: 50%;
  background-color: var(--sb-naranja);
  color: #fff;
  font-weight: 700;
  font-size: 2rem;
}

/* ============================================================
   13. Acordeón — para listas largas y colapsables (ej. municipios por
   departamento en un selector de zona de envío)
   ============================================================
   Es el componente nativo de Bootstrap — esta sección solo lo pone a
   tono: borde con --sb-borde en vez del gris de Bootstrap, fondo tenue
   --sb-fondo cuando está expandido (no el celeste por defecto), y foco
   naranja (misma regla que ya siguen inputs, checkboxes y botones: el
   naranja es el color de "activo/con foco" en todo el kit).
   ============================================================ */
.accordion-item {
  border-color: var(--sb-borde);
}

.accordion-button:not(.collapsed) {
  background-color: var(--sb-fondo);
  color: var(--sb-texto);
  box-shadow: none;
}

.accordion-button:focus {
  border-color: var(--sb-naranja);
  box-shadow: 0 0 0 0.2rem rgba(254, 129, 0, 0.25);
}

/* ============================================================
   14. Tarjeta seleccionable — elegir una entre varias opciones (ej. qué
   pasarela procesa el pago directo)
   ============================================================
   Un <input type="radio"> normal (ya sale naranja al marcarse, sección
   10) adentro de una .card; el borde de la tarjeta se resalta en naranja
   cuando su radio está marcado, con :has() — mismo criterio de "naranja
   = seleccionado" que ya sigue el resto del kit. Si el navegador no
   soporta :has() (todos los actuales sí, Firefox desde la 121), la
   tarjeta se ve normal pero sigue siendo funcional — no es una
   dependencia dura.
   ============================================================ */
.sb-tarjeta-opcion {
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.sb-tarjeta-opcion:has(.form-check-input:checked) {
  border-color: var(--sb-naranja);
  background-color: rgba(254, 129, 0, 0.05);
}

.sb-tarjeta-opcion.disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* ============================================================
   15. Editor de texto enriquecido — para contenido largo con formato
   propio (ej. el cuerpo de una Política de la tienda)
   ============================================================
   Barra de herramientas + área editable (contenteditable), sin librería
   externa: alcanza con document.execCommand para dar formato básico
   (negrita, cursiva, listas, encabezados, enlaces) a un texto legal o
   informativo. Botones de texto, no iconos — mismo criterio que las
   acciones de fila del resto del kit. El borde/foco sigue la misma regla
   que cualquier .form-control (naranja al enfocar).
   ============================================================ */
.sb-editor {
  border: 1px solid var(--sb-borde-fuerte);
  border-radius: var(--sb-radio);
  overflow: hidden;
}

.sb-editor-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  padding: 0.5rem;
  background-color: var(--sb-fondo);
  border-bottom: 1px solid var(--sb-borde-fuerte);
}

.sb-editor-btn {
  border: 1px solid transparent;
  background: none;
  border-radius: 0.375rem;
  min-width: 2rem;
  height: 2rem;
  padding: 0 0.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--sb-texto);
  font-size: 0.8125rem;
}

.sb-editor-btn:hover {
  background-color: var(--sb-borde);
}

.sb-editor-divider {
  width: 1px;
  height: 1.5rem;
  background-color: var(--sb-borde-fuerte);
  margin: 0 0.125rem;
}

.sb-editor-select {
  width: auto;
}

.sb-editor-area {
  min-height: 14rem;
  max-height: 28rem;
  overflow-y: auto;
  padding: 0.75rem 1rem;
  outline: none;
}

.sb-editor-area:focus {
  box-shadow: inset 0 0 0 2px rgba(254, 129, 0, 0.15);
}

.sb-editor-area ul,
.sb-editor-area ol {
  padding-left: 1.5rem;
}

.sb-editor-area h4 {
  font-size: 1rem;
  font-weight: 700;
}

.sb-editor-area:empty::before {
  content: attr(data-placeholder);
  color: var(--sb-secundario);
  pointer-events: none;
}

/* ============================================================
   16. Miniatura de imagen con zoom — para documentos adjuntos donde el
   contenido real importa más que decorar el marco (ej. factura de una
   venta, comprobante de pago).
   ============================================================
   Tamaño fijo SIN importar las dimensiones del archivo subido (nunca hay
   "salto" de layout entre una factura vertical y una horizontal);
   object-fit: contain conserva la imagen completa sin recortarla (a
   diferencia de "cover"), con un fondo neutro para las franjas que deja.
   El cursor de lupa (zoom-in) es la pista de que se puede ampliar; el
   detalle real se ve en un modal (mismo componente ya usado en el resto
   del kit, sección 11) al hacer clic — no una librería de lightbox nueva.
   ============================================================ */
.sb-miniatura-zoom {
  width: 220px;
  height: 220px;
  object-fit: contain;
  background-color: var(--sb-fondo);
  border: 1px solid var(--sb-borde);
  border-radius: var(--sb-radio);
  cursor: zoom-in;
  transition: border-color 0.15s ease;
}

.sb-miniatura-zoom:hover {
  border-color: var(--sb-naranja);
}

/* Lupa dentro del modal de imagen ampliada (ver .sb-miniatura-zoom arriba):
   al mover el mouse sobre la imagen, un círculo sigue el puntero mostrando
   esa misma zona a mayor aumento — para leer un detalle de una factura que
   salió borrosa por luz/resolución/estado del papel, sin salir de la
   pantalla. El cursor real se oculta (cursor: none) para que el círculo
   HAGA de puntero. JS mínimo por vista (ver Ventas/Detalle.cshtml en
   IntegraCommissions.Admin/.Cliente), sin librería de zoom externa. */
.sb-lupa-contenedor {
  position: relative;
  display: inline-block;
}

.sb-lupa-contenedor img {
  cursor: none;
}

.sb-lupa {
  position: absolute;
  display: none;
  width: 180px;
  height: 180px;
  border: 3px solid var(--sb-naranja);
  border-radius: 50%;
  pointer-events: none;
  background-repeat: no-repeat;
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.35);
}

/* ============================================================
   17. Modo oscuro — se activa poniendo [data-bs-theme="dark"] en <html>
   (Bootstrap 5.3 ya entiende ese atributo para sus propios componentes:
   tablas, modales, inputs, dropdowns se adaptan solos). Acá solo hace
   falta redefinir los tokens de la sección 1 que son neutros (fondo,
   superficie, texto, bordes) — el sidebar y los botones NO cambian: el
   azul/naranja de marca ya se ve bien sobre fondo oscuro, y el sidebar
   siempre fue azul oscuro incluso en modo claro.
   --sb-marron NO se redefine acá a propósito: también se usa como texto
   oscuro sobre naranja (.dropdown-item:active, ver sección 2), que debe
   seguir siendo oscuro en los dos temas por contraste. Por eso el texto
   de los badges color beige (reportada/inactiva/borrador/rol-client) se
   corrige aparte más abajo, sin tocar --sb-marron.
   Los demás badges (aprobada/enrevision/rechazada y sus alias creado/
   editado/eliminado/rol-admin/rol-seller) usan hex sueltos, no variables
   — llevan su propio bloque de reemplazo agrupado por color.
   ============================================================ */
:root[data-bs-theme="dark"] {
  --sb-fondo: #12181f;
  --sb-superficie: #1b232c;
  --sb-texto: #e9ecef;
  --sb-secundario: #98a2ad;
  --sb-borde: #2a333d;
  --sb-borde-fuerte: #3a4552;
  --sb-beige: #3a331a;
}

[data-bs-theme="dark"] .badge-estado-reportada,
[data-bs-theme="dark"] .badge-estado-inactiva,
[data-bs-theme="dark"] .badge-estado-borrador,
[data-bs-theme="dark"] .badge-estado-pagopendiente,
[data-bs-theme="dark"] .badge-estado-ordenpendiente,
[data-bs-theme="dark"] .badge-rol-client {
  color: #e0d093;
}

[data-bs-theme="dark"] .badge-estado-enrevision,
[data-bs-theme="dark"] .badge-estado-editado,
[data-bs-theme="dark"] .badge-estado-enproceso,
[data-bs-theme="dark"] .badge-rol-seller {
  background-color: #16223a;
  color: #8ec2ff;
}

[data-bs-theme="dark"] .badge-estado-aprobada,
[data-bs-theme="dark"] .badge-estado-activa,
[data-bs-theme="dark"] .badge-estado-publicado,
[data-bs-theme="dark"] .badge-estado-creado,
[data-bs-theme="dark"] .badge-estado-pagado,
[data-bs-theme="dark"] .badge-rol-admin {
  background-color: #10261d;
  color: #75c9a0;
}

[data-bs-theme="dark"] .badge-estado-rechazada,
[data-bs-theme="dark"] .badge-estado-eliminado {
  background-color: #341418;
  color: #ea868f;
}

[data-bs-theme="dark"] .badge-tipo {
  background-color: #495057;
  color: #fff;
}

/* Sección 18 (Tienda): mismo caso que los badges beige de arriba — el fondo
   ya se ajusta solo (--sb-beige/--sb-azul son variables), pero el texto
   marrón sobre beige pierde contraste en fondo oscuro y necesita su propio
   reemplazo, sin tocar --sb-marron (sigue sirviendo de texto oscuro sobre
   naranja en .tienda-promo-card.bg-naranja, que debe seguir oscuro en los
   dos temas). */
[data-bs-theme="dark"] .tienda-topbar,
[data-bs-theme="dark"] .tienda-topbar a,
[data-bs-theme="dark"] .tienda-categoria-icono .sb-icon {
  color: #e0d093;
}

[data-bs-theme="dark"] .tienda-precio-oferta {
  color: #ea868f;
}

/* ============================================================
   18. Tienda pública (ecommerce) — usado por _LayoutTienda.cshtml
   ============================================================
   Vitrina de cara al cliente (home, catálogo, producto) — layout público sin
   sidebar, distinto del shell administrativo de la sección 2. Inspirado en
   capturas de una plantilla externa (tema "Rozer"), adaptado a la paleta y
   al catálogo real de Smartbuy: se descartó el selector de idioma/moneda (un
   solo mercado, quetzales), los logos de "featured in" (marcas de Envato sin
   equivalente real) y los logos de pasarelas de pago del demo — la fila de
   medios de pago del footer queda en texto plano marcado TODO_ hasta
   confirmar qué pasarelas acepta la tienda de verdad. Ver Patrones/tienda-home.cshtml.
   ============================================================ */

/* Footer pegado abajo (2026-10-21): en pantallas con poco contenido
   (Pedido confirmado, Mi perfil sin mucho texto, etc.) el footer se
   quedaba a media página, dejando un vacío debajo de él en vez de llegar
   hasta el borde inferior de la ventana. Mismo criterio del truco
   `html:has(.tienda-header)` que ya usa la sección 24 (densidad) para
   aplicar algo SOLO a la tienda pública, sin tocar el panel admin (que ya
   resuelve esto distinto, con `.sb-app { display:flex; min-height:100vh }`
   como fila con sidebar, no como columna). `main` es el único hijo que
   crece (`flex: 1 0 auto`); topbar/header/footer mantienen su alto
   natural y el footer queda siempre al fondo, ya sea porque lo empuja el
   contenido o porque lo estira el espacio vacío. */
html:has(.tienda-header) body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

html:has(.tienda-header) main {
  flex: 1 0 auto;
}

/* Barra superior: aviso de bienvenida + acceso a cuenta. Un solo mercado
   (Guatemala, español, quetzales) — el demo original traía selector de
   idioma y moneda que acá no aplica. */
.tienda-topbar {
  background-color: var(--sb-beige);
  color: var(--sb-marron);
  font-size: 0.8rem;
  padding: 0.4rem 0;
}

.tienda-topbar .container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}

.tienda-topbar a {
  color: var(--sb-marron);
  text-decoration: none;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.tienda-topbar a:hover {
  text-decoration: underline;
}

.tienda-topbar .sb-icon {
  width: 16px;
  height: 16px;
}

/* Estado con sesión iniciada (2026-10-21) — "Hola, X" + "Mi Cuenta" +
   "Cerrar sesión". El botón de cerrar sesión vive dentro de un <form> POST
   (mismo criterio que el panel admin), así que se resetea para verse
   igual que los `<a>` de al lado, no como un botón nativo. */
.tienda-topbar-cuenta {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.tienda-topbar-cerrar-sesion button {
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  color: var(--sb-marron);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.tienda-topbar-cerrar-sesion button:hover {
  text-decoration: underline;
}

/* Header: logo + buscador + acciones (favoritos/carrito). */
.tienda-header {
  background: var(--sb-superficie);
  border-bottom: 1px solid var(--sb-borde);
  padding: 1rem 0;
}

.tienda-header .container {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}

/* Logo real de Smartbuy (img/logo_smartbuy_border_white.png) — reemplaza
   el logotipo de texto (Smart/buy en azul/naranja) que se usó mientras no
   había un recurso de marca real. Solo se limita el alto; el ancho fluye
   solo para no deformar el logo. */
.tienda-logo-tienda {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.tienda-logo-tienda img {
  height: 74px; /* 44px + 30% + 30%, pedido puntual del usuario */
  width: auto;
}

.tienda-buscador {
  flex: 1;
  min-width: 220px;
}

/* El input-group nativo de Bootstrap trae radios cuadrados; se envuelve en
   un borde propio con radio de píldora y se le quitan los radios/bordes a
   cada hijo, igual criterio que cualquier otro control del kit (radio 999px
   en controles compuestos). */
.tienda-buscador .input-group {
  border: 1px solid var(--sb-borde-fuerte);
  border-radius: 999px;
  overflow: hidden;
}

.tienda-buscador .input-group .form-select,
.tienda-buscador .input-group .form-control,
.tienda-buscador .input-group .btn {
  border: none;
  border-radius: 0;
  box-shadow: none;
}

.tienda-buscador .input-group .form-select {
  border-right: 1px solid var(--sb-borde);
  max-width: 170px;
  flex: 0 0 auto;
}

.tienda-buscador .input-group .btn {
  background-color: var(--sb-naranja);
  color: var(--sb-marron);
  padding-inline: 1.1rem;
}

.tienda-buscador .input-group .btn:hover {
  background-color: var(--sb-naranja-oscuro);
}

.tienda-buscador .input-group .btn .sb-icon {
  width: 18px;
  height: 18px;
}

.tienda-acciones {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Contador de favoritos/carrito — mismo .sb-icon-btn del header admin
   (sección 2), solo le suma un badge circular en la esquina. */
.tienda-icono-contador {
  position: relative;
}

.tienda-badge-contador {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 0.25rem;
  border-radius: 999px;
  background-color: var(--sb-naranja);
  color: #fff;
  font-size: 0.65rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* Menú hamburguesa del header de la tienda — abre `#offcanvasMenu`.
   Reemplaza la barra de navegación horizontal (Inicio/Catálogo/Ofertas/...)
   que tenía la primera versión de la home: el acceso a categorías y al
   resto de enlaces ahora vive en el panel de categorías (solo en la home,
   ver `.tienda-categorias-panel`) y en este offcanvas (en cualquier
   pantalla de la tienda). Usa `.sb-icon-btn` (el mismo botón circular con
   hover del resto de íconos del header — búsqueda, favoritos, carrito),
   NO `.sb-btn-menu` del panel admin: ese es un ícono suelto sin fondo,
   pensado para sentarse junto al título de una página, y acá se veía
   descolgado al lado de íconos con su propio botón circular. */
.tienda-header .sb-icon-btn {
  flex-shrink: 0;
}

/* Panel "Todas las categorías" — vive junto al hero SOLO en la home
   (`.tienda-hero-fila`, ver abajo) y en el sidebar de Catálogo. El resto de
   la tienda llega a las categorías por el offcanvas del ícono de
   hamburguesa, no por este panel. SIN `overflow:hidden`: el flyout de
   subcategorías (más abajo) necesita salirse del cuadro — las esquinas se
   redondean en la barra de título y en el último ítem, no recortando el
   contenedor completo.

   Bug 2026-10-20: `height: 100%` NO va en la regla base. En la home es el
   único elemento de su columna junto al carrusel, así que estirarlo a la
   altura completa tiene sentido — pero en Catálogo comparte columna con
   las tarjetas de filtro (Precio, Color, Marca...) que van DEBAJO de él.
   Un hijo con `height:100%` cuyo padre (la columna `.col-lg-3`) todavía no
   tiene una altura definida (depende del estirado por flex, que a su vez
   depende de este panel) crea una dependencia circular: el navegador la
   resuelve inflando el panel a la altura completa de la columna ya
   estirada, y entonces las tarjetas que siguen después se quedan sin
   espacio y se desbordan fuera de la columna, encima del footer. Por eso
   el alto completo se pide solo donde de verdad aplica (`.tienda-hero-fila`,
   home), no acá. */
.tienda-categorias-panel {
  border: 1px solid var(--sb-borde);
  border-radius: var(--sb-radio);
}

.tienda-hero-fila .tienda-categorias-panel {
  height: 100%;
}

.tienda-categorias-panel-titulo {
  background-color: var(--sb-azul);
  color: #fff;
  font-weight: 700;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.85rem 1rem;
  border-radius: var(--sb-radio) var(--sb-radio) 0 0;
}

.tienda-categorias-panel .nav {
  flex-direction: column;
}

/* Cada categoría es un <li> propio (no solo el <a>) porque el flyout de
   subcategorías (si existen) vive como hermano del link dentro del mismo
   <li> — necesita `position:relative` en el <li> para anclarse ahí. */
.tienda-categorias-panel li {
  position: relative;
}

.tienda-categorias-panel .nav-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  color: var(--sb-texto);
  font-weight: 600;
  font-size: 0.9rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--sb-borde);
}

/* Corrección: como cada <a class="nav-link"> es el único hijo de su <li>,
   `.nav-link:last-child` era siempre verdadero para TODOS (cada uno es el
   último hijo de SU PROPIO <li>) — quitaba el borde de todos, no solo del
   último de la lista. El selector correcto compara contra `li:last-child`. */
.tienda-categorias-panel li:last-child .nav-link {
  border-bottom: none;
  border-radius: 0 0 var(--sb-radio) var(--sb-radio);
}

.tienda-categorias-panel .nav-link:hover {
  background-color: var(--sb-fondo);
  color: var(--sb-naranja-oscuro);
}

/* Categoría activa — en la home el panel de categorías no tiene "activa"
   (es un menú, no un filtro), así que este modificador solo entra en
   juego en Catálogo, pero es una extensión directa de
   `.tienda-categorias-panel` (arriba), no un componente aparte — por eso
   sigue viviendo acá, dentro de la sección 18, en vez de en la sección 20
   (ver el pointer al final del archivo). */
.tienda-categorias-panel .nav-link.active {
  background-color: var(--sb-fondo);
  color: var(--sb-naranja-oscuro);
}

/* Ícono de flecha — solo lo llevan las categorías con subcategorías
   (ver iconos.md > "Flecha derecha"), nunca decorativo en las que no
   tienen nada que desplegar. */
.tienda-categorias-panel .nav-link .sb-icon {
  width: 16px;
  height: 16px;
  color: var(--sb-secundario);
  flex-shrink: 0;
}

/* Flyout de subcategorías — aparece a la derecha del panel al pasar el
   mouse (o con teclado, `:focus-within`) sobre la categoría. Reemplaza el
   primer intento (lista anidada indentada debajo de la categoría activa):
   el usuario pidió replicar el flyout de la plantilla de referencia en vez
   de un acordeón inline. `:has()` no hace falta acá — el propio `:hover`
   del <li> alcanza. */
.tienda-categoria-flyout {
  position: absolute;
  left: 100%;
  top: 0;
  min-width: 200px;
  background: var(--sb-superficie);
  border: 1px solid var(--sb-borde);
  border-radius: var(--sb-radio);
  box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.12);
  padding: 0.75rem 1rem;
  z-index: 20;
  opacity: 0;
  visibility: hidden;
  transform: translateX(-8px);
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.tienda-categorias-panel li:hover .tienda-categoria-flyout,
.tienda-categorias-panel li:focus-within .tienda-categoria-flyout {
  opacity: 1;
  visibility: visible;
  transform: translateX(0);
}

.tienda-categoria-flyout a {
  display: block;
  padding: 0.35rem 0;
  color: var(--sb-texto);
  text-decoration: none;
  font-size: 0.9rem;
  white-space: nowrap;
}

.tienda-categoria-flyout a:hover {
  color: var(--sb-naranja-oscuro);
}

/* Banner ancho de una sola tarjeta, a todo el ancho de la sección — misma
   `.tienda-promo-card`, solo horizontal en vez de apilada. */
.tienda-promo-card.ancho {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 140px;
}

.tienda-promo-card.ancho h3 {
  font-size: 1.4rem;
}

.tienda-promo-card.ancho .btn {
  flex-shrink: 0;
}

/* Banner mediano — 2 por fila (`col-md-6`) en vez de uno solo a todo el
   ancho (`.ancho`, arriba) o 3 chicas (`.tienda-promo-card` sin
   modificador). Se queda vertical como la base, solo más alta. */
.tienda-promo-card.mediano {
  min-height: 220px;
  padding: 2rem;
}

.tienda-promo-card.mediano h3 {
  font-size: 1.5rem;
}

/* Tabs de "Compra por categoría" alineadas a la derecha del título de
   sección (mismo `.tienda-titulo-seccion` de siempre, ahora con
   `.sb-tabs` como segundo hijo en vez de en su propia fila) — sin el
   borde inferior de `.sb-tabs` (sección 9) para no chocar con el
   subrayado naranja del título. */
.tienda-titulo-seccion .sb-tabs {
  border-bottom: none;
  margin-bottom: 0;
}

/* Grilla compacta — pedido puntual para "Compra por categoría": ~20% menos
   alta que el resto de grillas de producto del kit (que se quedan
   cuadradas, sección 18) — imagen 5:4 en vez de 1:1, y menos padding en
   las tarjetas. Es un modificador acotado a esta sección, no un cambio al
   componente base `.sb-producto-card`/`.tienda-promo-card`. */
.tienda-grilla-compacta .sb-producto-imagen {
  aspect-ratio: 5 / 4;
}

.tienda-grilla-compacta .sb-producto-card {
  padding: 0.8rem;
}

.tienda-grilla-compacta .tienda-promo-card {
  padding: 1.4rem;
}

/* Fila del hero en la home: panel de categorías + carrusel — el panel se
   oculta bajo 992px (en móvil se llega a las categorías por el offcanvas,
   no tiene sentido duplicarlo aquí). Ajuste 2026-09-17: las 2 tiles
   apiladas al lado del hero (`.tienda-promo-card.compacto`) se quitaron a
   pedido del usuario — el hero pasó de `col-lg-6` a `col-lg-9` para
   ocupar el espacio que dejaron. La clase `.compacto` se eliminó del kit
   (sin usos restantes). */
.tienda-hero-fila .tienda-hero {
  height: 100%;
}

/* Sublinks de subcategoría bajo cada tarjeta de "Categorías populares" —
   mismo criterio de contenido de la variante de plantilla, sin fotografía
   de stock (el kit no tiene fotos de catálogo, ver sección 18 arriba). */
.tienda-categoria-subenlaces {
  margin-top: 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.tienda-categoria-subenlaces a {
  color: var(--sb-secundario);
  font-size: 0.78rem;
  text-decoration: none;
}

.tienda-categoria-subenlaces a:hover {
  color: var(--sb-azul);
  text-decoration: underline;
}

/* Hero de la home — degradado azul/azul-petróleo (nunca fondo de foto de
   stock: el kit no usa fotografía de producto, solo íconos e ilustración
   plana, mismo criterio que el resto de las tarjetas). Carrusel nativo de
   Bootstrap (misma disciplina que .sb-tabs: solo se le pone la piel de
   marca encima, no se reemplaza su JS). */
.tienda-hero {
  background: linear-gradient(120deg, var(--sb-azul) 0%, var(--sb-azul-petroleo) 100%);
  color: #fff;
  border-radius: var(--sb-radio);
  overflow: hidden;
}

.tienda-hero-eyebrow {
  text-transform: uppercase;
  font-size: 0.8rem;
  letter-spacing: 0.05em;
  font-style: italic;
  font-weight: 600;
  color: #ffd9ad;
}

.tienda-hero .sb-icon-decorativo {
  width: 220px;
  height: 220px;
  color: rgba(255, 255, 255, 0.25);
}

.tienda-hero .carousel-indicators [data-bs-target] {
  background-color: #fff;
  opacity: 0.5;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.tienda-hero .carousel-indicators .active {
  opacity: 1;
}

/* Franja de beneficios (envío/devoluciones/soporte/pago seguro). */
.tienda-feature {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}

.tienda-feature .sb-icon {
  width: 32px;
  height: 32px;
  color: var(--sb-azul);
  flex-shrink: 0;
}

.tienda-feature-titulo {
  font-weight: 700;
  margin-bottom: 0.1rem;
}

.tienda-feature-texto {
  color: var(--sb-secundario);
  font-size: 0.85rem;
}

/* Tarjetas de promoción (3 destacados). Naranja es el único fondo que
   necesita texto oscuro encima (mismo criterio de accesibilidad del CLAUDE.md
   raíz: "sobre botones naranja usar texto oscuro"), por eso es un modificador
   aparte en vez del color blanco por defecto. */
.tienda-promo-card {
  border-radius: var(--sb-radio);
  padding: 1.75rem;
  color: #fff;
  min-height: 180px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.35rem;
  position: relative;
  overflow: hidden;
}

.tienda-promo-card.bg-naranja {
  background-color: var(--sb-naranja);
  color: var(--sb-marron);
}

.tienda-promo-eyebrow {
  text-transform: uppercase;
  font-size: 0.75rem;
  font-weight: 700;
  opacity: 0.85;
}

.tienda-promo-card h3 {
  font-weight: 800;
  margin: 0;
  font-size: 1.35rem;
}

.tienda-promo-card .sb-icon-decorativo {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
  width: 64px;
  height: 64px;
  opacity: 0.3;
}

/* Encabezado de sección con subrayado naranja — mismo "activo = naranja",
   aplicado como acento de título en vez de estado de nav. */
.tienda-titulo-seccion {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
  gap: 1rem;
  flex-wrap: wrap;
}

.tienda-titulo-seccion h2 {
  font-size: 1.1rem;
  font-weight: 700;
  border-bottom: 3px solid var(--sb-naranja);
  display: inline-block;
  padding-bottom: 0.4rem;
  margin: 0;
}

/* Categorías destacadas: círculo beige con ícono, se invierte a naranja en
   hover (mismo "activo/hover = naranja" del resto del kit). */
.tienda-categoria-card {
  text-decoration: none;
  text-align: center;
  color: var(--sb-texto);
  display: block;
  height: 100%;
  border: 1px solid var(--sb-borde);
  border-radius: var(--sb-radio);
  padding: 1.25rem 1rem;
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.tienda-categoria-card:hover {
  border-color: var(--sb-borde-fuerte);
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.06);
}

.tienda-categoria-icono {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background-color: var(--sb-beige);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 0.6rem;
  transition: background-color 0.15s ease;
}

.tienda-categoria-icono .sb-icon {
  width: 30px;
  height: 30px;
  color: var(--sb-marron);
}

.tienda-categoria-card:hover .tienda-categoria-icono {
  background-color: var(--sb-naranja);
}

.tienda-categoria-card:hover .tienda-categoria-icono .sb-icon {
  color: #fff;
}

.tienda-categoria-nombre {
  font-size: 0.85rem;
  font-weight: 600;
}

/* Tarjeta de producto — un solo componente para Destacados/Novedades/Ofertas
   del día (con .tienda-deal-card como variante horizontal), en vez de un
   componente distinto por sección. Sin fotografía de producto (el kit no
   tiene fotos de catálogo todavía): un ícono neutro sobre fondo --sb-fondo
   marca el lugar de la imagen real. */
.sb-producto-card {
  border: 1px solid var(--sb-borde);
  border-radius: var(--sb-radio);
  padding: 1rem;
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  text-decoration: none;
  color: inherit;
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.sb-producto-card:hover {
  border-color: var(--sb-borde-fuerte);
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.06);
}

.sb-producto-imagen {
  position: relative;
  aspect-ratio: 1 / 1;
  background-color: var(--sb-fondo);
  border-radius: 0.65rem;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.5rem;
}

/* Badge de % de descuento — validado contra el sitio real de Smartbuy
   Store (sandbox-store.smartbuy.com.gt), que sí lo muestra en la tarjeta
   de producto. Mismo rojo que `.tienda-precio-oferta` (abajo), pero sólido
   en vez de solo texto, porque acá necesita contraste sobre la imagen. */
.tienda-badge-descuento {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  background-color: #842029;
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
}

.sb-producto-imagen .sb-icon {
  width: 40px;
  height: 40px;
  color: var(--sb-secundario);
}

.sb-producto-categoria {
  text-transform: uppercase;
  font-size: 0.7rem;
  color: var(--sb-secundario);
  letter-spacing: 0.03em;
}

.sb-producto-nombre {
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--sb-texto);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Calificación con estrellas — naranja de marca en vez de amarillo genérico,
   así no se introduce un color fuera de la paleta solo para esto. */
.sb-producto-rating {
  display: flex;
  align-items: center;
  gap: 0.15rem;
}

.sb-producto-rating .sb-icon {
  width: 14px;
  height: 14px;
}

.sb-producto-rating .sb-icon.lleno {
  color: var(--sb-naranja);
  fill: var(--sb-naranja);
}

.sb-producto-rating .sb-icon.vacio {
  color: var(--sb-borde-fuerte);
}

.sb-producto-precio {
  margin-top: auto;
  font-weight: 700;
}

.sb-producto-precio-anterior {
  color: var(--sb-secundario);
  text-decoration: line-through;
  font-weight: 400;
  font-size: 0.85rem;
  margin-right: 0.4rem;
}

/* Mismo rojo que .badge-estado-rechazada (sección 6) — un precio de oferta
   reusa el tono "negativo/atención" que ya existe en vez de inventar un rojo
   nuevo; el reemplazo de modo oscuro vive en la sección 17. */
.tienda-precio-oferta {
  color: #842029;
}

/* Variante horizontal de .sb-producto-card, para "Ofertas del día". */
.tienda-deal-card {
  border: 1px solid var(--sb-borde);
  border-radius: var(--sb-radio);
  padding: 1.25rem;
  display: flex;
  gap: 1.25rem;
  align-items: center;
  height: 100%;
  text-decoration: none;
  color: inherit;
}

.tienda-deal-card .sb-producto-imagen {
  width: 120px;
  height: 120px;
  flex-shrink: 0;
  margin-bottom: 0;
}

.tienda-deal-card .sb-producto-descripcion {
  color: var(--sb-secundario);
  font-size: 0.85rem;
}

/* Footer — azul de marca (no cambia entre temas, mismo criterio que el
   sidebar del panel admin). */
.tienda-footer {
  background-color: var(--sb-azul);
  color: rgba(255, 255, 255, 0.85);
  padding: 3rem 0 1.5rem;
}

.tienda-footer h3 {
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  color: #fff;
  margin-bottom: 1rem;
}

.tienda-footer a {
  color: rgba(255, 255, 255, 0.8);
  text-decoration: none;
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.9rem;
}

.tienda-footer a:hover {
  color: #fff;
  text-decoration: underline;
}

.tienda-footer .form-control {
  border-radius: 999px 0 0 999px;
}

.tienda-footer-social {
  display: flex;
  gap: 0.5rem;
  margin-top: 1rem;
}

.tienda-footer-social a {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0;
}

.tienda-footer-social .sb-icon {
  width: 16px;
  height: 16px;
}

.tienda-footer-bottom {
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  margin-top: 2rem;
  padding-top: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  font-size: 0.85rem;
}

/* Medios de pago: texto plano, no logos — TODO_ hasta confirmar con el
   cliente qué pasarelas/tarjetas acepta realmente la tienda. */
.tienda-pago-badge {
  background-color: rgba(255, 255, 255, 0.12);
  border-radius: 0.4rem;
  padding: 0.3rem 0.6rem;
  font-size: 0.75rem;
  font-weight: 700;
}

/* Franja de marcas — arriba del footer, en la home (Patrones/tienda-home.cshtml).
   Texto + ícono, nunca un logo de marca de tercero sin confirmar (mismo
   criterio que `.tienda-pago-badge`): solo Tecno es una marca real del
   catálogo de comisiones (CLAUDE.md raíz); el resto queda `TODO_MARCAS`
   hasta que el cliente confirme qué otras marcas destacar. */
.tienda-marcas {
  border: 1px solid var(--sb-borde);
  border-radius: var(--sb-radio);
  padding: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 2.5rem;
}

.tienda-marcas-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--sb-secundario);
  font-weight: 700;
  font-size: 1.05rem;
}

.tienda-marcas-item .sb-icon {
  width: 22px;
  height: 22px;
}

/* Botón "volver arriba" — fijo, aparece solo después de bajar (JS en
   _LayoutTienda.cshtml). Color oscuro fijo, no `--sb-texto`: ese token SÍ
   cambia en modo oscuro (pasa a claro), y este botón debe verse igual en
   los dos temas, igual criterio que el azul del sidebar/footer. */
.tienda-scroll-arriba {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  border: none;
  background-color: #212529;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0.35rem 0.75rem rgba(0, 0, 0, 0.25);
  z-index: 15;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s ease;
}

.tienda-scroll-arriba.visible {
  opacity: 1;
  visibility: visible;
}

.tienda-scroll-arriba:hover {
  background-color: var(--sb-naranja-oscuro);
}

.tienda-scroll-arriba .sb-icon {
  width: 20px;
  height: 20px;
}

/* ============================================================
   19. Carrito y checkout
   ============================================================
   Mini-carrito (offcanvas nativo de Bootstrap — el mismo componente que ya
   usa el sidebar del panel admin en móvil, sección 2, solo con la piel de
   marca encima) + pantalla completa de carrito (Patrones/tienda-carrito.cshtml).

   Excepción documentada a "Confirmar un borrado: siempre modal" (ver
   README > Estándar de medidas): quitar una línea del carrito NO abre
   modal. El carrito es un estado de sesión, no un registro persistido —
   quitar un producto es trivialmente reversible (agregarlo de nuevo desde
   el catálogo), a diferencia de borrar un Vendedor o una Categoría. Se
   reusa `.btn-close` (la misma X de modales/offcanvas) en vez de
   `.btn-outline-danger` + modal.
   ============================================================ */

/* Breadcrumb — la tienda no tiene sidebar que ubique al visitante, así que
   necesita su propia señal de "dónde estoy" (el panel admin no la necesita:
   el ítem activo del sidebar ya cumple ese rol). */
.tienda-breadcrumb {
  background-color: var(--sb-fondo);
  padding: 0.75rem 1.25rem;
  border-radius: var(--sb-radio);
  margin-bottom: 1.5rem;
}

/* Ajuste estético 2026-10-21 (se veía "plano"): separador tipográfico
   (›) en vez del "/" por defecto de Bootstrap, enlaces en negrita con un
   fondo sutil al pasar el mouse (mismo azul de marca translúcido que ya
   usa `.sb-tarjeta-opcion` para su estado activo, sección 14 — no se
   inventó un tono nuevo) y el ítem activo en negrita en vez de solo un
   color distinto. */
.tienda-breadcrumb .breadcrumb {
  margin: 0;
  --bs-breadcrumb-divider: "›";
}

.tienda-breadcrumb .breadcrumb-item + .breadcrumb-item::before {
  color: var(--sb-borde-fuerte);
  font-weight: 700;
}

.tienda-breadcrumb a {
  color: var(--sb-azul);
  font-weight: 600;
  text-decoration: none;
  padding: 0.15rem 0.5rem;
  margin: -0.15rem -0.5rem;
  border-radius: 999px;
  transition: background-color 0.15s ease;
}

.tienda-breadcrumb a:hover {
  background-color: rgba(23, 79, 176, 0.08);
  text-decoration: none;
}

.tienda-breadcrumb .breadcrumb-item.active {
  color: var(--sb-secundario);
  font-weight: 700;
}

/* Pasos de compra (Carrito / Pago / Pedido confirmado) — reusa el mismo
   círculo numerado `.sb-tab-paso` de los wizards (sección 9), solo que acá
   vive suelto en vez de adentro de una pestaña de `.sb-tabs`. */
.tienda-pasos {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 2rem;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.tienda-paso {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--sb-secundario);
  font-weight: 700;
  font-size: 0.9rem;
}

.tienda-paso .sb-tab-paso {
  width: 2rem;
  height: 2rem;
  font-size: 0.9rem;
}

.tienda-paso.activo {
  color: var(--sb-naranja-oscuro);
}

.tienda-paso.activo .sb-tab-paso {
  background-color: var(--sb-naranja);
  color: #fff;
}

.tienda-paso-linea {
  width: 4rem;
  height: 2px;
  background-color: var(--sb-borde-fuerte);
  margin: 0 1rem;
}

@media (max-width: 576px) {
  .tienda-paso-linea {
    width: 1.5rem;
    margin: 0 0.5rem;
  }
}

/* Carrito vacío — sin caja de alerta de color (mismo criterio del kit:
   nunca decorar con `.alert` de color lo que un ícono + texto ya explican). */
.tienda-vacio {
  text-align: center;
  padding: 3rem 1rem;
}

.tienda-vacio .sb-icon {
  width: 64px;
  height: 64px;
  color: var(--sb-borde-fuerte);
  margin-bottom: 1rem;
}

.tienda-vacio p {
  color: var(--sb-secundario);
  margin-bottom: 1.5rem;
}

/* Fila de producto dentro de la tabla del carrito. */
.tienda-carrito-producto {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.tienda-carrito-producto .sb-producto-imagen {
  width: 64px;
  height: 64px;
  margin-bottom: 0;
  flex-shrink: 0;
}

/* Stepper de cantidad — botones de texto (−/+), no íconos, mismo criterio
   minimalista que los botones de `.sb-editor` (sección 15). */
.tienda-cantidad {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--sb-borde-fuerte);
  border-radius: 999px;
  overflow: hidden;
}

.tienda-cantidad button {
  border: none;
  background: transparent;
  width: 2rem;
  height: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--sb-texto);
  font-weight: 700;
  cursor: pointer;
}

.tienda-cantidad button:hover {
  background-color: var(--sb-fondo);
  color: var(--sb-naranja-oscuro);
}

.tienda-cantidad input {
  width: 2.25rem;
  border: none;
  text-align: center;
  padding: 0;
  color: var(--sb-texto);
  background: transparent;
  -moz-appearance: textfield;
}

.tienda-cantidad input::-webkit-outer-spin-button,
.tienda-cantidad input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Mini-carrito (offcanvas) — misma lista que la tabla completa, en tarjetas
   apiladas en vez de filas (no entra una tabla en un panel de 380px). */
.tienda-minicarrito-item {
  display: flex;
  gap: 0.75rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--sb-borde);
}

.tienda-minicarrito-item:last-child {
  border-bottom: none;
}

.tienda-minicarrito-item .sb-producto-imagen {
  width: 64px;
  height: 64px;
  margin-bottom: 0;
  flex-shrink: 0;
}

.tienda-minicarrito-item-info {
  flex: 1;
  min-width: 0;
}

.tienda-minicarrito-item-nombre {
  font-weight: 600;
  font-size: 0.85rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.tienda-minicarrito-item-cantidad {
  color: var(--sb-secundario);
  font-size: 0.8rem;
}

.tienda-minicarrito-subtotal {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 700;
  padding: 1rem 0;
  border-top: 1px solid var(--sb-borde);
  margin: 0.5rem 0 1rem;
}

/* ============================================================
   20. Catálogo — filtros de la tienda pública
   ============================================================
   Patrones/tienda-catalogo.cshtml: casi toda la pantalla reusa componentes
   que ya existen en vez de crear los suyos — no hay CSS exclusivo de
   catálogo agrupado en un solo bloque, por eso esta sección es solo un
   mapa de dónde vive cada pieza:
     - `.card`, `.form-check`, `.sb-producto-card`, `.pagination`,
       `.tienda-categoria-card` — reuso directo, sin cambios.
     - `.tienda-categorias-panel` (con `.nav-link.active` y el flyout de
       subcategorías `.tienda-categoria-flyout`) — sección 18: es el mismo
       panel de categorías de la home, Catálogo solo le agrega el estado
       "activa". Ver el comentario junto a `.tienda-categorias-panel`.
     - `.tienda-filtro-color` (swatch clickeable del filtro "Color") —
       sección 7, junto a `.sb-color-swatch` (su base no interactiva).
   Si un futuro cambio agrega algo que de verdad sea exclusivo de Catálogo
   y no encaje en ninguna sección existente, ese es el momento de
   agregarle CSS propio acá — hasta entonces, esta sección se queda como
   índice para no duplicar ni mover código que ya vive bien donde está.
   ============================================================ */

/* ============================================================
   21. Aviso con personaje — modal que pide atención sin ser un error
   ============================================================
   Cuerpo de un modal (.modal-body.sb-aviso) con la mascota de Smartbuy
   (el robot "SB") señalando hacia el texto: "tienes N ventas por revisar". Es un
   modal del kit como cualquier otro (sección 11: header con título +
   cerrar, footer con la acción secundaria y la principal) — lo único
   propio es este cuerpo en dos columnas. En móvil se apila (dibujo
   arriba, texto centrado debajo).

   La mascota es Partials/_AvatarSenalando.cshtml, que carga
   img/avatar.png (arte entregado por el cliente). Úsalo con moderación — un aviso por pantalla y solo
   para algo que de verdad espera una acción del usuario; si aparece en
   todos lados deja de llamar la atención. Ver Patrones/aviso-con-personaje.cshtml.
   ============================================================ */
.sb-aviso {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  text-align: center;
}

@media (min-width: 576px) {
  .sb-aviso {
    flex-direction: row;
    gap: 1.5rem;
    text-align: left;
  }
}

/* La imagen original es apaisada (1536x1024, fondo transparente) con la mascota a la
   izquierda y aire vacío a la derecha: aspect-ratio + object-fit: cover la recortan a
   solo la mascota sin tocar el archivo, y object-position corre la "ventana" lo justo
   para que entre la mano que señala. Si se cambia la imagen por otra con otro encuadre,
   estos dos números son los que hay que reajustar. */
.sb-aviso-avatar {
  width: 11rem;
  aspect-ratio: 1.14;
  object-fit: cover;
  object-position: 33% center;
  flex-shrink: 0;
}

/* La cantidad que se está avisando: mismo tamaño y azul que .sb-stat-valor. */
.sb-aviso-cifra {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1;
  color: var(--sb-azul);
}

/* ============================================================
   22. Aviso de espera — pantalla cubierta mientras algo viaja
   ============================================================
   Capa a pantalla completa con spinner + una frase corta ("Preparando
   foto…", "Enviando venta…"). La crea y la quita site.js
   (mostrarAvisoCarga / ocultarAvisoCarga); en las vistas no se escribe
   HTML, solo atributos:
     - <form data-sb-aviso-envio="Enviando venta…"> — al enviar muestra el
       aviso e ignora un segundo envío (evita ventas duplicadas por tocar
       dos veces el botón con mala señal).
     - <input type="file" data-sb-reducir-imagen="1600"> — al elegir una
       foto la achica en el navegador a ese lado máximo (px) antes de
       subirla, mostrando el aviso mientras tanto.
   Es para esperas que el usuario no puede acelerar (subir un archivo,
   guardar). No usarlo para cargas de página normales ni como confirmación:
   para eso están el modal (sección 11) y el aviso con personaje (21).
   z-index por encima del modal (1055) y del offcanvas (1045) de Bootstrap.
   ============================================================ */
.sb-aviso-carga {
  position: fixed;
  inset: 0;
  z-index: 1090;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background-color: rgba(0, 0, 0, 0.45);
}

.sb-aviso-carga[hidden] {
  display: none;
}

.sb-aviso-carga-caja {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  min-width: 14rem;
  padding: 1.5rem 2rem;
  border-radius: 0.75rem;
  background-color: var(--sb-superficie);
  color: var(--sb-texto);
  text-align: center;
}

.sb-aviso-carga .spinner-border {
  color: var(--sb-naranja);
}

/* ============================================================
   23. Varios ítems dentro de un registro — recuadro, agregar y aviso
   ============================================================
   Para un registro que contiene una lista de elementos del mismo tipo que
   se capturan y se revisan uno por uno. Caso real: una venta es una factura
   y trae uno o varios teléfonos, cada uno con su producto, su precio y su
   propia comisión (IntegraCommissions: Cliente/Views/Ventas/Registrar.cshtml,
   Admin/Views/Ventas/_TelefonosDeVenta.cshtml y _ModalAprobarVenta.cshtml).

   Tres piezas:
     - `.sb-telefono` — el recuadro de un ítem. En un formulario lleva sus
       campos; en un detalle, su tabla llave/valor; en el modal de aprobar,
       su switch (sección 10) y su monto.
     - `.sb-telefono-agregar` — botón "agregar otro", con la misma forma que
       el recuadro pero borde punteado azul: ocupa el lugar del siguiente
       ítem, para que se lea como parte del formulario y no pase
       desapercibido. Azul y no naranja a propósito: el naranja queda para
       la acción principal de la pantalla. No agrega nada mientras haya un
       ítem incompleto (lo valida el script de la vista con las mismas
       reglas del formulario).
     - `.sb-badge-telefonos` — etiqueta naranja "N teléfonos" que avisa, en
       listados y junto al título del detalle, que el registro trae más de
       un ítem. Texto oscuro sobre naranja por contraste. Solo se muestra
       cuando hay más de uno.
   Los nombres dicen "telefono" porque así nacieron en el código real; al
   reusarlos para otro tipo de ítem conviene crear el alias con el nombre
   que corresponda en vez de forzar este.
   ============================================================ */
.sb-telefono {
  border: 1px solid var(--sb-borde);
  border-radius: var(--sb-radio);
  padding: 1rem;
  margin-bottom: 1rem;
}

.sb-telefono-agregar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  padding: 1rem;
  margin-bottom: 1rem;
  border: 2px dashed var(--sb-azul);
  border-radius: var(--sb-radio);
  background-color: transparent;
  color: var(--sb-azul);
  font-weight: 600;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.sb-telefono-agregar[hidden] {
  display: none;
}

.sb-telefono-agregar:hover,
.sb-telefono-agregar:focus-visible {
  border-style: solid;
  background-color: var(--sb-azul);
  color: #fff;
  outline: none;
}

.sb-telefono-agregar .sb-icon {
  width: 1.5rem;
  height: 1.5rem;
}

[data-bs-theme="dark"] .sb-telefono-agregar {
  border-color: #8ec2ff;
  color: #8ec2ff;
}

[data-bs-theme="dark"] .sb-telefono-agregar:hover,
[data-bs-theme="dark"] .sb-telefono-agregar:focus-visible {
  border-color: var(--sb-azul);
  color: #fff;
}

.sb-badge-telefonos {
  display: inline-block;
  margin-left: 0.35rem;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  background-color: var(--sb-naranja);
  color: #212529;
  font-size: 0.75rem;
  font-weight: 700;
  white-space: nowrap;
}

/* ============================================================
   24. Densidad en computadoras (monitor y laptop)
   ============================================================
   En computadora la app se veía grande (pedido de José, 2026-10-15). Se compacta todo:

   - Tamaño base más chico: el kit (y Bootstrap) miden casi todo en rem, así que textos,
     botones, campos y espacios bajan parejo, como un zoom del navegador, sin desacomodar nada.
     Dos niveles:
       · cualquier computadora (monitor): 13 px en vez de 16, como un zoom del 81 %;
       · laptop de pantalla baja (1366 × 768, 820 px de alto o menos): 12 px, como un 75 %.
   - Menú lateral compacto en toda computadora: menos relleno, ícono de 24 px y texto un poco
     más chico, para que quepan todos los módulos sin scroll. (Lo que mide en px, como los
     íconos, no baja solo con el tamaño base: por eso se ajusta aquí.)

   Solo desde 992 px de ancho (en el celular el menú es un panel deslizable y nada cambia).
   Ajuste 2026-10-20: se extendió de solo el panel administrativo (html:has(.sb-app), el
   contenedor de _Layout.cshtml) también a la tienda pública (html:has(.tienda-header), el
   header de _LayoutTienda) — mismo tamaño base en toda la app, consistente con
   IntegraCatalog/Admin/Cliente. _LayoutCuenta (login) sigue sin tocarse: es una pantalla
   centrada de una sola columna, no tiene el problema de "se ve grande" que esto resuelve.
   Las reglas del menú lateral compacto (sb-nav*) siguen exclusivas de html:has(.sb-app):
   la tienda no tiene sidebar.
   Si se agrega un componente con medidas fijas en px, revisa que se vea bien aquí también
   (ver nota sobre el logo de la tienda más abajo).
   ============================================================ */
@media (min-width: 992px) {
  html:has(.sb-app),
  html:has(.tienda-header) {
    font-size: 13px;
  }

  .sb-sidebar-subtitulo {
    padding-bottom: 0.5rem;
  }

  .sb-nav {
    gap: 0.3rem;
    padding: 0.35rem 0.6rem;
  }

  .sb-nav-link {
    gap: 0.3rem;
    padding: 0.55rem 0.35rem;
    border-radius: 0.8rem;
    font-size: 0.78rem;
  }

  /* Solo el ícono del menú: los del encabezado y las pestañas ya son de 20 px. */
  .sb-nav .sb-icon {
    width: 24px;
    height: 24px;
  }

  /* El logo de la tienda mide en px fijos (sección 18), así que no baja con el tamaño
     base — a diferencia del resto, que sí lo sigue por estar en rem. Se achica un poco
     acá para que no quede desproporcionado contra el header ya compacto. */
  .tienda-logo-tienda img {
    height: 62px;
  }
}

/* Laptop de pantalla baja: un punto más compacto. */
@media (min-width: 992px) and (max-height: 820px) {
  html:has(.sb-app),
  html:has(.tienda-header) {
    font-size: 12px;
  }
}

/* ============================================================
   25. Detalle de producto (tienda pública)
   ============================================================
   Patrones/tienda-producto.cshtml. Casi todo reusa componentes que ya
   existen (`.sb-producto-imagen`, `.sb-producto-rating`, `.tienda-cantidad`,
   `.sb-tabs`, `.sb-avatar`, `.sb-producto-card` para "Productos
   relacionados") — acá solo lo que de verdad es nuevo:

     - Galería: imagen principal grande + miniaturas. El kit no tiene
       fotografía real de producto (ver sección 18), así que hoy todas las
       miniaturas muestran el mismo ícono de categoría; lo que se demuestra
       es la interacción (clic en miniatura = se activa), no fotos
       distintas por ángulo. Reemplazar por fotos reales en cuanto existan.
     - Selector de calificación en "Escribe una reseña": mismo truco de
       checkbox/radio oculto + `:has()`/`~` que `.tienda-filtro-color`
       (sección 7), pero con estrellas en vez de un círculo de color, y en
       orden inverso en el HTML para que `:checked ~ label` encienda todas
       las estrellas hasta la elegida.
   ============================================================ */
.tienda-galeria-principal {
  aspect-ratio: 1 / 1;
}

/* Mismo tamaño "ícono grande ilustrativo" que .tienda-vacio (carrito
   vacío, arriba) — no se inventó un tercer tamaño de ícono grande. */
.tienda-galeria-principal .sb-icon {
  width: 64px;
  height: 64px;
}

.tienda-galeria-miniaturas {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.tienda-galeria-miniatura {
  width: 64px;
  height: 64px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 0.65rem;
  background-color: var(--sb-fondo);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

/* Mismo tamaño que los íconos del header/pestañas (iconos.md, escala de
   tamaños) — no se inventó un tamaño nuevo solo para la miniatura. */
.tienda-galeria-miniatura .sb-icon {
  width: 20px;
  height: 20px;
  color: var(--sb-secundario);
}

.tienda-galeria-miniatura.activa {
  border-color: var(--sb-naranja);
}

/* Ícono inline junto a "En stock" y "Agregar a favoritos" — mismo criterio
   de la "Escala de tamaños" de iconos.md: el tamaño lo da una regla de CSS
   atada al contexto, no un width/height suelto en el SVG. */
.tienda-disponibilidad .sb-icon,
.tienda-favoritos-link .sb-icon {
  width: 16px;
  height: 16px;
}

/* Selector de estrellas de "Escribe una reseña" — orden inverso en el HTML
   (5,4,3,2,1) + row-reverse para que `~` encienda la estrella elegida y
   todas las que están a su izquierda. */
.tienda-estrellas-picker {
  display: inline-flex;
  flex-direction: row-reverse;
  gap: 0.2rem;
}

.tienda-estrellas-picker input {
  display: none;
}

.tienda-estrellas-picker label {
  cursor: pointer;
  margin: 0;
}

/* Mismo tamaño que los íconos del header/pestañas — no se inventó un
   tamaño nuevo solo para este selector de estrellas. */
.tienda-estrellas-picker label .sb-icon {
  width: 20px;
  height: 20px;
  color: var(--sb-borde-fuerte);
}

.tienda-estrellas-picker input:checked ~ label .sb-icon,
.tienda-estrellas-picker label:hover .sb-icon,
.tienda-estrellas-picker label:hover ~ label .sb-icon {
  color: var(--sb-naranja);
  fill: var(--sb-naranja);
}

/* ============================================================
   26. Realizar pago con tarjeta (tienda pública)
   ============================================================
   Patrones/tienda-pago-tarjeta.cshtml. Casi todo reusa componentes
   existentes (`.sb-tarjeta-opcion` para elegir pasarela de cuotas,
   `.badge.text-bg-light.border` para las marcas de tarjeta — mismo
   patrón que "Efectivo/ACH" en `.sb-producto-card`, sección 18 — y
   `.tienda-disponibilidad` para "Tu pedido será procesado inmediatamente",
   sección 25). Lo único nuevo es el tamaño del ícono de escudo junto a la
   nota de 3D Secure. */
.tienda-aviso-pago .sb-icon {
  width: 20px;
  height: 20px;
}

/* ============================================================
   27. Mis pedidos y detalle de pedido (tienda pública)
   ============================================================
   Patrones/tienda-mis-pedidos.cshtml y Patrones/tienda-pedido-detalle.cshtml.
   Reusan `table table-sm`/`.sb-tabla-wrapper`, `.badge-estado-*` (sección
   6), `.sb-producto-imagen`, `.tienda-vacio` y `.tienda-disponibilidad`
   (sección 25) — acá solo dos tamaños de ícono propios de estas pantallas. */
.tienda-metodo-pago .sb-icon {
  width: 18px;
  height: 18px;
}

.tienda-pedido-miniatura {
  width: 64px;
  height: 64px;
}
