/* =====================================================================
   NetwilOne · Capa de componentes
   =====================================================================

   Se carga la ULTIMA, despues de app.css / store.css / workspace.css. Esos
   tres archivos suman 6.400 lineas escritas en tandas distintas y se pisan
   entre si; esta capa es la que manda sobre los componentes compartidos.

   Dos reglas de la casa:

   1. Ni un color escrito a mano. Todo sale de las variables que el motor
      de temas emite desde la base de datos, asi que cambiar el color
      principal en el panel repinta la plataforma entera sin tocar CSS.

   2. Se acota a `.store-workspace` o `.app-shell` para ganar por
      especificidad limpia, sin un solo !important.

   Orden: base · botones · insignias · tarjetas · formularios · tablas ·
   avisos · esqueletos · vacios · pestanas · paginacion · movil.
   ===================================================================== */

/* =====================================================================
   0 · Base
   ===================================================================== */

:where(.store-workspace, .app-shell) {
    /* Escalones de espacio: todo lo de aqui abajo mide con estos. */
    --ui-1: 4px;
    --ui-2: 8px;
    --ui-3: 12px;
    --ui-4: 16px;
    --ui-5: 22px;
    --ui-6: 30px;

    /* El tema trae su propio redondeo; esto solo pone el suelo. */
    --ui-radius: var(--radius, 10px);
    --ui-radius-sm: var(--radius-sm, 6px);
    --ui-radius-lg: var(--radius-lg, 16px);

    /* Rapido y discreto: el brief pide que se sienta veloz, no animado. */
    --ui-quick: 130ms;
    --ui-ease: cubic-bezier(.2, .8, .3, 1);

    /* Area minima para un dedo. */
    --ui-tap: 44px;
}

/* Un foco visible e igual en todas partes. Se ve solo con teclado, que es
   justo cuando hace falta. */
:is(.store-workspace, .app-shell) :is(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--ui-radius-sm);
}

/* Quien pide menos movimiento no lo tiene. Va arriba del todo para que
   valga para todo lo que sigue. */
@media (prefers-reduced-motion: reduce) {
    :is(.store-workspace, .app-shell) *,
    :is(.store-workspace, .app-shell) *::before,
    :is(.store-workspace, .app-shell) *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }
}

/* =====================================================================
   1 · Botones

   Un solo cuerpo y variantes encima. Todos comparten alto, radio, foco y
   la misma microinteraccion: 1px hacia arriba, nada de saltos.
   ===================================================================== */

:is(.store-workspace, .app-shell) .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ui-2);
    min-height: var(--ui-tap);
    padding: 10px 18px;
    border: 1px solid transparent;
    border-radius: var(--ui-radius);
    background: var(--raise, var(--surface-2));
    color: var(--text);
    font: inherit;
    font-size: .92rem;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: -.01em;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    position: relative;
    isolation: isolate;
    transition: background var(--ui-quick) var(--ui-ease),
                border-color var(--ui-quick) var(--ui-ease),
                color var(--ui-quick) var(--ui-ease),
                transform var(--ui-quick) var(--ui-ease),
                box-shadow var(--ui-quick) var(--ui-ease);
}

:is(.store-workspace, .app-shell) .btn:hover { transform: translateY(-1px); }
:is(.store-workspace, .app-shell) .btn:active { transform: translateY(0); }

/* ---- Principal */
:is(.store-workspace, .app-shell) .btn-primary {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--on-primary);
    box-shadow: 0 1px 2px rgba(var(--primary-rgb), .22);
}
:is(.store-workspace, .app-shell) .btn-primary:hover {
    background: var(--primary-hover, var(--primary));
    border-color: var(--primary-hover, var(--primary));
    box-shadow: 0 4px 14px rgba(var(--primary-rgb), .3);
}
:is(.store-workspace, .app-shell) .btn-primary:active { background: var(--primary-active, var(--primary)); }

/* ---- Secundario: cuerpo, sin gritar */
:is(.store-workspace, .app-shell) .btn-secondary {
    background: var(--raise-2, var(--surface-3));
    border-color: var(--border);
    color: var(--text);
}
:is(.store-workspace, .app-shell) .btn-secondary:hover { border-color: var(--border-2); }

/* ---- Contorno */
:is(.store-workspace, .app-shell) .btn-outline {
    background: transparent;
    border-color: var(--border-2);
    color: var(--text);
}
:is(.store-workspace, .app-shell) .btn-outline:hover {
    border-color: var(--primary);
    color: var(--primary);
    background: rgba(var(--primary-rgb), .07);
}

/* ---- Fantasma: el de andar por casa */
:is(.store-workspace, .app-shell) .btn-ghost {
    background: transparent;
    border-color: var(--border);
    color: var(--text-2);
}
:is(.store-workspace, .app-shell) .btn-ghost:hover {
    background: var(--raise, var(--surface-2));
    border-color: var(--border-2);
    color: var(--text);
}

/* ---- Estados semanticos */
:is(.store-workspace, .app-shell) .btn-danger {
    background: transparent;
    border-color: rgba(var(--danger-rgb), .4);
    color: var(--danger);
}
:is(.store-workspace, .app-shell) .btn-danger:hover {
    background: var(--danger-dim);
    border-color: var(--danger);
}
:is(.store-workspace, .app-shell) .btn-danger-solid {
    background: var(--danger);
    border-color: var(--danger);
    color: #fff;
}

:is(.store-workspace, .app-shell) .btn-success {
    background: var(--success);
    border-color: var(--success);
    color: #fff;
}
:is(.store-workspace, .app-shell) .btn-warning {
    background: transparent;
    border-color: rgba(var(--warning-rgb), .45);
    color: var(--warning);
}
:is(.store-workspace, .app-shell) .btn-warning:hover { background: var(--warning-dim); }

/* ---- Tamanos */
:is(.store-workspace, .app-shell) .btn-sm {
    min-height: 36px;
    padding: 7px 13px;
    font-size: .85rem;
    border-radius: var(--ui-radius-sm);
}
:is(.store-workspace, .app-shell) .btn-lg {
    min-height: 52px;
    padding: 14px 26px;
    font-size: 1rem;
}
:is(.store-workspace, .app-shell) .btn-block { width: 100%; }

/* ---- Boton de solo icono: cuadrado y con area de dedo */
/* Sin `display` a proposito: el menu de movil y el boton de cerrar la
   barra lateral son .icon-button que nacen ocultos, y declararlo aqui los
   resucitaba en escritorio. El centrado ya viene de la regla base. */
:is(.store-workspace, .app-shell) .icon-button {
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--ui-radius-sm);
    background: transparent;
    color: var(--text-2);
    cursor: pointer;
    transition: background var(--ui-quick) var(--ui-ease),
                color var(--ui-quick) var(--ui-ease),
                border-color var(--ui-quick) var(--ui-ease);
}
:is(.store-workspace, .app-shell) .icon-button:hover {
    background: var(--raise, var(--surface-2));
    color: var(--text);
    border-color: var(--border-2);
}

/* ---- Inhabilitado: se ve que no se puede, y no reacciona */
:is(.store-workspace, .app-shell) .btn:disabled,
:is(.store-workspace, .app-shell) .btn[disabled],
:is(.store-workspace, .app-shell) .btn[aria-disabled="true"] {
    opacity: .45;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

/* ---- Cargando: el texto se apaga y gira un aro encima. El ancho no
        cambia, asi que la fila no da un salto al pulsar. */
:is(.store-workspace, .app-shell) .btn.is-loading {
    color: transparent;
    pointer-events: none;
}
:is(.store-workspace, .app-shell) .btn.is-loading::after {
    content: "";
    position: absolute;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    border: 2px solid currentColor;
    border-top-color: transparent;
    color: var(--on-primary);
    animation: ui-spin .6s linear infinite;
}
:is(.store-workspace, .app-shell) .btn-ghost.is-loading::after,
:is(.store-workspace, .app-shell) .btn-outline.is-loading::after { color: var(--text-2); }

@keyframes ui-spin { to { transform: rotate(360deg); } }

/* =====================================================================
   2 · Insignias de estado

   Nunca solo color: cada una lleva un punto delante. Quien no distingue
   verde de rojo sigue leyendo la palabra y viendo la forma.
   ===================================================================== */

:is(.store-workspace, .app-shell) .badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--raise, var(--surface-2));
    color: var(--text-2);
    font-size: .76rem;
    font-weight: 600;
    letter-spacing: .01em;
    line-height: 1.45;
    white-space: nowrap;
}
:is(.store-workspace, .app-shell) .badge::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
    opacity: .85;
}

:is(.store-workspace, .app-shell) .badge-ok,
:is(.store-workspace, .app-shell) .badge-green {
    color: var(--success);
    background: var(--success-dim);
    border-color: rgba(var(--success-rgb), .3);
}
:is(.store-workspace, .app-shell) .badge-warn {
    color: var(--warning);
    background: var(--warning-dim);
    border-color: rgba(var(--warning-rgb), .3);
}
:is(.store-workspace, .app-shell) .badge-red,
:is(.store-workspace, .app-shell) .badge-out {
    color: var(--danger);
    background: var(--danger-dim);
    border-color: rgba(var(--danger-rgb), .3);
}
:is(.store-workspace, .app-shell) .badge-info {
    color: var(--info);
    background: var(--info-dim);
    border-color: rgba(var(--info-rgb), .3);
}
:is(.store-workspace, .app-shell) .badge-brand {
    color: var(--primary);
    background: rgba(var(--primary-rgb), .12);
    border-color: rgba(var(--primary-rgb), .32);
}
:is(.store-workspace, .app-shell) .badge-muted {
    color: var(--faint);
    background: transparent;
}

/* =====================================================================
   3 · Tarjetas
   ===================================================================== */

:is(.store-workspace, .app-shell) .card {
    border: 1px solid var(--border);
    border-radius: var(--ui-radius-lg);
    background: var(--surface);
    padding: var(--ui-5);
}

:is(.store-workspace, .app-shell) .card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ui-3);
    flex-wrap: wrap;
    margin-bottom: var(--ui-4);
    padding-bottom: var(--ui-3);
    border-bottom: 1px solid var(--line-soft, var(--border));
}
:is(.store-workspace, .app-shell) .card-head h2,
:is(.store-workspace, .app-shell) .card-head h3 {
    margin: 0;
    font-size: 1rem;
    font-weight: 650;
    letter-spacing: -.02em;
}

/* Una linea de color arriba, del ancho de la tarjeta: marca la importante
   sin llenarla de borde. */
:is(.store-workspace, .app-shell) .card-accent {
    position: relative;
    overflow: hidden;
    border-color: rgba(var(--primary-rgb), .3);
}
:is(.store-workspace, .app-shell) .card-accent::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 2px;
    background: var(--accent-grad, var(--primary));
}

/* ---- Tarjeta de cifra del panel */
:is(.store-workspace, .app-shell) .stat {
    position: relative;
    padding: var(--ui-4) var(--ui-5);
    border: 1px solid var(--border);
    border-radius: var(--ui-radius-lg);
    background: var(--surface);
    transition: border-color var(--ui-quick) var(--ui-ease),
                transform var(--ui-quick) var(--ui-ease);
}
:is(.store-workspace, .app-shell) .stat:hover {
    border-color: var(--border-2);
    transform: translateY(-1px);
}
:is(.store-workspace, .app-shell) .stat .label,
:is(.store-workspace, .app-shell) .stat-label {
    display: block;
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--faint);
}
:is(.store-workspace, .app-shell) .stat strong,
:is(.store-workspace, .app-shell) .stat .value {
    display: block;
    margin-top: var(--ui-2);
    font-size: clamp(1.5rem, 1.2rem + 1vw, 1.95rem);
    font-weight: 700;
    letter-spacing: -.035em;
    line-height: 1.05;
    font-variant-numeric: tabular-nums;
}
:is(.store-workspace, .app-shell) .stat-hint,
:is(.store-workspace, .app-shell) .stat small {
    display: block;
    margin-top: 6px;
    font-size: .82rem;
    color: var(--muted);
}

/* =====================================================================
   4 · Formularios
   ===================================================================== */

:is(.store-workspace, .app-shell) .field { margin-bottom: var(--ui-4); }

:is(.store-workspace, .app-shell) .field > label,
:is(.store-workspace, .app-shell) label.field-label {
    display: block;
    margin-bottom: 7px;
    font-size: .86rem;
    font-weight: 600;
    color: var(--text-2);
}

:is(.store-workspace, .app-shell) input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
:is(.store-workspace, .app-shell) select,
:is(.store-workspace, .app-shell) textarea {
    width: 100%;
    min-height: var(--ui-tap);
    padding: 11px 13px;
    border: 1px solid var(--border-2);
    border-radius: var(--ui-radius);
    background: var(--bg);
    color: var(--text);
    font: inherit;
    font-size: .94rem;
    transition: border-color var(--ui-quick) var(--ui-ease),
                box-shadow var(--ui-quick) var(--ui-ease),
                background var(--ui-quick) var(--ui-ease);
}
:is(.store-workspace, .app-shell) textarea { min-height: 108px; resize: vertical; line-height: 1.6; }

:is(.store-workspace, .app-shell) input::placeholder,
:is(.store-workspace, .app-shell) textarea::placeholder { color: var(--faint); }

:is(.store-workspace, .app-shell) input:focus,
:is(.store-workspace, .app-shell) select:focus,
:is(.store-workspace, .app-shell) textarea:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px var(--focus-ring, rgba(var(--primary-rgb), .35));
}

:is(.store-workspace, .app-shell) input:disabled,
:is(.store-workspace, .app-shell) select:disabled,
:is(.store-workspace, .app-shell) textarea:disabled {
    opacity: .55;
    cursor: not-allowed;
    background: var(--raise, var(--surface-2));
}

/* ---- Estados de validacion. El color no va solo: el mensaje explica. */
:is(.store-workspace, .app-shell) .field.is-error input,
:is(.store-workspace, .app-shell) .field.is-error select,
:is(.store-workspace, .app-shell) .field.is-error textarea,
:is(.store-workspace, .app-shell) input[aria-invalid="true"] {
    border-color: var(--danger);
}
:is(.store-workspace, .app-shell) .field.is-error input:focus { box-shadow: 0 0 0 3px rgba(var(--danger-rgb), .3); }
:is(.store-workspace, .app-shell) .field-error {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
    font-size: .84rem;
    color: var(--danger);
}
:is(.store-workspace, .app-shell) .field.is-ok input { border-color: var(--success); }

:is(.store-workspace, .app-shell) .hint,
:is(.store-workspace, .app-shell) .field .hint {
    margin-top: 6px;
    font-size: .82rem;
    line-height: 1.5;
    color: var(--muted);
}

/* ---- Subir archivo. El borde a trazos dice "aqui va algo" sin necesidad
        de explicarlo, y el box-sizing no es decorativo: sin el, el relleno
        se suma al 100% y el campo sobresale de la pantalla en movil. */
:is(.store-workspace, .app-shell) input[type="file"] {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    min-height: var(--ui-tap);
    padding: 10px 12px;
    border: 1px dashed var(--border-2);
    border-radius: var(--ui-radius);
    background: var(--bg);
    color: var(--muted);
    font: inherit;
    font-size: .88rem;
    cursor: pointer;
    transition: border-color var(--ui-quick) var(--ui-ease);
}
:is(.store-workspace, .app-shell) input[type="file"]:hover { border-color: var(--primary); }
:is(.store-workspace, .app-shell) input[type="file"]::file-selector-button {
    margin-right: 12px;
    padding: 7px 13px;
    border: 1px solid var(--border-2);
    border-radius: var(--ui-radius-sm);
    background: var(--raise, var(--surface-2));
    color: var(--text);
    font: inherit;
    font-size: .85rem;
    font-weight: 600;
    cursor: pointer;
}

/* ---- Casillas y radios con area de dedo */
:is(.store-workspace, .app-shell) label.checkbox {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    min-height: 34px;
    padding: 5px 0;
    cursor: pointer;
}
:is(.store-workspace, .app-shell) input[type="checkbox"],
:is(.store-workspace, .app-shell) input[type="radio"] {
    width: 18px;
    height: 18px;
    margin: 1px 0 0;
    flex: none;
    accent-color: var(--primary);
    cursor: pointer;
}

/* ---- Interruptor */
:is(.store-workspace, .app-shell) .switch {
    position: relative;
    width: 42px;
    height: 24px;
    flex: none;
    border-radius: 999px;
    background: var(--border-2);
    transition: background var(--ui-quick) var(--ui-ease);
}
:is(.store-workspace, .app-shell) .switch::after {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--text);
    transition: transform var(--ui-quick) var(--ui-ease);
}
:is(.store-workspace, .app-shell) .switch-row input:checked ~ .switch { background: var(--primary); }
:is(.store-workspace, .app-shell) .switch-row input:checked ~ .switch::after {
    transform: translateX(18px);
    background: var(--on-primary);
}

/* =====================================================================
   5 · Tablas

   En escritorio, tabla. En movil NO una tabla encogida: cada fila se
   convierte en una ficha y cada celda se etiqueta con su columna, que
   viaja en data-label desde la vista.
   ===================================================================== */

:is(.store-workspace, .app-shell) .table-wrap {
    border: 1px solid var(--border);
    border-radius: var(--ui-radius-lg);
    background: var(--surface);
    overflow: hidden;
}

:is(.store-workspace, .app-shell) .table {
    width: 100%;
    border-collapse: collapse;
    font-size: .92rem;
}
:is(.store-workspace, .app-shell) .table th {
    padding: 12px 16px;
    text-align: left;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--faint);
    background: var(--raise, var(--surface-2));
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
:is(.store-workspace, .app-shell) .table td {
    padding: 14px 16px;
    border-bottom: 1px solid var(--line-soft, var(--border));
    vertical-align: middle;
}
:is(.store-workspace, .app-shell) .table tbody tr:last-child td { border-bottom: 0; }
:is(.store-workspace, .app-shell) .table tbody tr {
    transition: background var(--ui-quick) var(--ui-ease);
}
:is(.store-workspace, .app-shell) .table tbody tr:hover { background: var(--raise, var(--surface-2)); }

/* Numeros alineados para poder compararlos de un vistazo */
:is(.store-workspace, .app-shell) .table .num,
:is(.store-workspace, .app-shell) .table .price { font-variant-numeric: tabular-nums; }

/* =====================================================================
   6 · Avisos y notificaciones
   ===================================================================== */

:is(.store-workspace, .app-shell) .alert {
    display: flex;
    align-items: flex-start;
    gap: var(--ui-3);
    padding: 13px 16px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--muted);
    border-radius: var(--ui-radius);
    background: var(--surface);
    font-size: .9rem;
    line-height: 1.55;
}
:is(.store-workspace, .app-shell) .alert-success,
:is(.store-workspace, .app-shell) .alert-ok {
    border-left-color: var(--success);
    background: var(--success-dim);
    border-color: rgba(var(--success-rgb), .28);
}
:is(.store-workspace, .app-shell) .alert-warning {
    border-left-color: var(--warning);
    background: var(--warning-dim);
    border-color: rgba(var(--warning-rgb), .28);
}
:is(.store-workspace, .app-shell) .alert-danger,
:is(.store-workspace, .app-shell) .alert-error {
    border-left-color: var(--danger);
    background: var(--danger-dim);
    border-color: rgba(var(--danger-rgb), .28);
}
:is(.store-workspace, .app-shell) .alert-info {
    border-left-color: var(--info);
    background: var(--info-dim);
    border-color: rgba(var(--info-rgb), .28);
}

/* ---- Aviso flotante: entra desde arriba y se queda quieto */
:is(.store-workspace, .app-shell) .toast-stack {
    position: fixed;
    top: 16px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: var(--ui-2);
    width: min(440px, calc(100vw - 32px));
    pointer-events: none;
}
:is(.store-workspace, .app-shell) .toast-stack > * {
    pointer-events: auto;
    box-shadow: var(--shadow-lg, 0 18px 42px rgba(0, 0, 0, .4));
    animation: ui-toast-in .26s var(--ui-ease) both;
}
@keyframes ui-toast-in {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: none; }
}

/* =====================================================================
   7 · Esqueletos de carga

   Una pantalla en blanco parece rota; un esqueleto parece rapido.
   ===================================================================== */

:is(.store-workspace, .app-shell) .skeleton {
    position: relative;
    overflow: hidden;
    border-radius: var(--ui-radius-sm);
    background: var(--raise, var(--surface-2));
}
:is(.store-workspace, .app-shell) .skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(var(--text-rgb), .07), transparent);
    transform: translateX(-100%);
    animation: ui-shimmer 1.35s infinite;
}
@keyframes ui-shimmer { to { transform: translateX(100%); } }

:is(.store-workspace, .app-shell) .skeleton-text { height: 12px; margin-bottom: 8px; }
:is(.store-workspace, .app-shell) .skeleton-text:last-child { width: 65%; margin-bottom: 0; }
:is(.store-workspace, .app-shell) .skeleton-title { height: 20px; width: 45%; margin-bottom: 14px; }
:is(.store-workspace, .app-shell) .skeleton-img { aspect-ratio: 16 / 10; border-radius: var(--ui-radius); }
:is(.store-workspace, .app-shell) .skeleton-card {
    padding: var(--ui-4);
    border: 1px solid var(--border);
    border-radius: var(--ui-radius-lg);
    background: var(--surface);
}

/* =====================================================================
   8 · Estados vacios
   ===================================================================== */

:is(.store-workspace, .app-shell) .empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--ui-3);
    padding: clamp(30px, 6vw, 56px) var(--ui-4);
    color: var(--muted);
    font-size: .95rem;
    line-height: 1.6;
}
:is(.store-workspace, .app-shell) .empty-icon {
    display: grid;
    place-items: center;
    width: 54px;
    height: 54px;
    border-radius: 50%;
    background: rgba(var(--primary-rgb), .1);
    border: 1px solid rgba(var(--primary-rgb), .22);
    color: var(--primary);
}
:is(.store-workspace, .app-shell) .empty-icon .ui-icon { width: 24px; height: 24px; }
:is(.store-workspace, .app-shell) .empty h3 {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 650;
    color: var(--text);
    letter-spacing: -.02em;
}
:is(.store-workspace, .app-shell) .empty p { margin: 0; max-width: 44ch; }

/* =====================================================================
   9 · Pestanas y paginacion
   ===================================================================== */

:is(.store-workspace, .app-shell) .filter-tabs,
:is(.store-workspace, .app-shell) .tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 5px;
    border: 1px solid var(--border);
    border-radius: var(--ui-radius);
    background: var(--raise, var(--surface-2));
}
:is(.store-workspace, .app-shell) .filter-tabs > a,
:is(.store-workspace, .app-shell) .tabs > a {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-height: 36px;
    padding: 7px 14px;
    border-radius: var(--ui-radius-sm);
    color: var(--muted);
    font-size: .88rem;
    font-weight: 600;
    transition: background var(--ui-quick) var(--ui-ease), color var(--ui-quick) var(--ui-ease);
}
:is(.store-workspace, .app-shell) .filter-tabs > a:hover,
:is(.store-workspace, .app-shell) .tabs > a:hover { color: var(--text); }
:is(.store-workspace, .app-shell) .filter-tabs > a.active,
:is(.store-workspace, .app-shell) .tabs > a.active {
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, .2));
}

:is(.store-workspace, .app-shell) .pager a,
:is(.store-workspace, .app-shell) .pager span {
    min-width: 38px;
    min-height: 38px;
}

/* =====================================================================
   10 · Movil

   No se encoge: se reordena. La tabla es lo que mas cambia.
   ===================================================================== */

@media (max-width: 680px) {
    /* Cada fila pasa a ser una ficha. La etiqueta de cada dato sale del
       atributo data-label de la celda; si la vista no lo trae, la celda se
       muestra igual, solo que sin su titulo. */
    :is(.store-workspace, .app-shell) .table-responsive,
    :is(.store-workspace, .app-shell) .table-responsive thead,
    :is(.store-workspace, .app-shell) .table-responsive tbody,
    :is(.store-workspace, .app-shell) .table-responsive tr,
    :is(.store-workspace, .app-shell) .table-responsive td { display: block; width: 100%; }

    /* La cabecera sobra: cada celda ya lleva su titulo delante. Oculta a
       medias seguia ocupando ancho y empujaba la pagina de lado. */
    :is(.store-workspace, .app-shell) .table-responsive thead { display: none; }

    /* Y el ancho minimo de 520px que la tabla trae para poder desplazarse
       en horizontal deja de tener sentido cuando ya no es una tabla. */
    :is(.store-workspace, .app-shell) table.table-responsive { min-width: 0; }

    :is(.store-workspace, .app-shell) .table-responsive tbody tr {
        margin-bottom: var(--ui-3);
        padding: var(--ui-3) var(--ui-4);
        border: 1px solid var(--border);
        border-radius: var(--ui-radius);
        background: var(--surface);
    }
    :is(.store-workspace, .app-shell) .table-responsive tbody tr:last-child { margin-bottom: 0; }

    :is(.store-workspace, .app-shell) .table-responsive td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--ui-4);
        padding: 7px 0;
        border: 0;
        text-align: right;
    }
    :is(.store-workspace, .app-shell) .table-responsive td::before {
        content: attr(data-label);
        flex: none;
        font-size: .72rem;
        font-weight: 600;
        letter-spacing: .09em;
        text-transform: uppercase;
        color: var(--faint);
        text-align: left;
    }
    /* Una celda sin etiqueta ocupa el ancho entero: suele ser el nombre o
       la fila de acciones. */
    :is(.store-workspace, .app-shell) .table-responsive td:not([data-label]) { justify-content: flex-start; text-align: left; }
    :is(.store-workspace, .app-shell) .table-responsive td[data-label=""]::before { display: none; }

    :is(.store-workspace, .app-shell) .table-wrap {
        border: 0;
        border-radius: 0;
        background: transparent;
        overflow: visible;
    }

    /* Acciones a lo ancho, para el pulgar. */
    :is(.store-workspace, .app-shell) .table-responsive td .btn { flex: 1; }
}

/* =====================================================================
   11 · Acabado

   Lo que separa una interfaz correcta de una que parece hecha por alguien:
   nada de esto se ve por separado, todo junto se nota.
   ===================================================================== */

/* ------------------------------------------------ Tipografia -------- */

/* El tamano optico no es un capricho. Bricolage Grotesque trae letras
   distintas para cuerpo pequeno y para titular grande: mas abiertas abajo,
   mas ajustadas arriba. Sin esto se pide la fuente variable y se usa una
   sola forma, que es tirar la mitad del archivo. */
:is(.store-workspace, .app-shell) {
    font-optical-sizing: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* El interletrado se aprieta segun crece el cuerpo. Un titular de 44px con
   el mismo espaciado que un parrafo de 15px se ve suelto y blando; es de
   los detalles que mas delatan una plantilla. */
:is(.store-workspace, .app-shell) :is(h1, .h1) { letter-spacing: -.035em; }
:is(.store-workspace, .app-shell) :is(h2, .h2) { letter-spacing: -.028em; }
:is(.store-workspace, .app-shell) :is(h3, .h3) { letter-spacing: -.02em; }
:is(.store-workspace, .app-shell) :is(h4, h5, h6) { letter-spacing: -.012em; }

/* Los titulos se reparten en lineas parejas en vez de dejar una palabra
   suelta abajo; los parrafos evitan la palabra huerfana al final. */
:is(.store-workspace, .app-shell) :is(h1, h2, h3, .welcome-hero h1, .detail-lede h1) {
    text-wrap: balance;
}
:is(.store-workspace, .app-shell) p { text-wrap: pretty; }

/* Titulares con la familia de titulos, no con la de cuerpo. Es la
   diferencia entre una tienda con voz y una plantilla. */
:is(.store-workspace, .app-shell) :is(h1, h2, .stat strong, .stat .value) {
    font-family: var(--font-display, inherit);
}

/* ------------------------------------------------ Cifras ------------ */

/* Numeros de ancho fijo en todo lo que sea dinero, cantidad o fecha. Sin
   esto una columna de precios baila, y con esto se pueden comparar de un
   vistazo: es lo que hace una tabla legible. */
:is(.store-workspace, .app-shell) :is(.price, .stat strong, .stat .value, .num,
    .sum-item-price, .purchase-summary strong, .rail-balance, .welcome-stats b,
    .buy-price .price-xl, td, .badge) {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1, "lnum" 1;
}

/* El simbolo de moneda, un punto por debajo y algo mas claro: el ojo va al
   numero, que es lo que importa. */
:is(.store-workspace, .app-shell) .price { font-feature-settings: "tnum" 1, "ss01" 1; }

/* ------------------------------------------------ Superficies ------- */

/* Una linea de luz de 1px en el borde de arriba de cada superficie
   levantada. Es como se ve una pieza real iluminada desde arriba, y es el
   detalle que hace que una tarjeta parezca material en vez de un rectangulo
   de color. Solo en temas oscuros: sobre papel blanco no hay luz que
   reflejar. */
:is(.store-workspace, .app-shell) :is(.card, .stat, .buy-card, .table-wrap, .rail-card) {
    position: relative;
}
:is(.store-workspace, .app-shell) :is(.card, .stat, .buy-card, .rail-card)::after {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 1px;
    margin-inline: 12px;
    border-radius: inherit;
    background: linear-gradient(90deg, transparent, rgba(var(--text-rgb), .09), transparent);
    pointer-events: none;
}
/* En tema claro la luz sobra y el borde se lleva el trabajo. */
[data-light="1"] :is(.card, .stat, .buy-card, .rail-card)::after { display: none; }

/* La tarjeta con acento ya tiene su propia linea arriba: dos se pelean. */
:is(.store-workspace, .app-shell) .card-accent::after { display: none; }

/* ------------------------------------------------ Detalles del sistema */

/* La seleccion de texto con el color de la tienda. Cuesta una linea y casi
   nadie lo hace. */
:is(.store-workspace, .app-shell) ::selection {
    background: rgba(var(--primary-rgb), .28);
    color: var(--text);
}

/* La barra de desplazamiento deja de ser la del sistema operativo. */
:is(.store-workspace, .app-shell) {
    scrollbar-width: thin;
    scrollbar-color: var(--border-2) transparent;
}
:is(.store-workspace, .app-shell) ::-webkit-scrollbar { width: 10px; height: 10px; }
:is(.store-workspace, .app-shell) ::-webkit-scrollbar-track { background: transparent; }
:is(.store-workspace, .app-shell) ::-webkit-scrollbar-thumb {
    border: 3px solid transparent;
    border-radius: 999px;
    background: var(--border-2);
    background-clip: content-box;
}
:is(.store-workspace, .app-shell) ::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: content-box; }

/* Aqui iba un fondo para todas las imagenes, para que una a medio cargar no
   diera un fogonazo blanco. Se retiro: donde la imagen se muestra entera
   dentro de su marco, ese fondo asomaba por los lados como dos barras
   grises. El fogonazo dura milisegundos; las barras se veian siempre. */

/* Nada de resaltado azul del sistema al tocar en el movil: ahi ya estan los
   estados de cada componente. */
:is(.store-workspace, .app-shell) :is(a, button, label, summary) {
    -webkit-tap-highlight-color: transparent;
}

/* Los enlaces del cuerpo de texto, subrayados por debajo de la linea base
   para que el subrayado no corte las colas de las letras. */
:is(.store-workspace, .app-shell) p a:not(.btn) {
    color: var(--primary);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    text-decoration-color: rgba(var(--primary-rgb), .4);
    transition: text-decoration-color var(--ui-quick) var(--ui-ease);
}
:is(.store-workspace, .app-shell) p a:not(.btn):hover { text-decoration-color: currentColor; }

/* ------------------------------------------------ Entrada en escena -- */

/* Un solo gesto de entrada, corto y hacia arriba. Repetido en toda la
   plataforma se lee como una firma; distinto en cada pantalla, como ruido. */
@keyframes ui-rise {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
:is(.store-workspace, .app-shell) .rise { animation: ui-rise .32s var(--ui-ease) both; }

/* Las rejillas de tarjetas entran escalonadas, muy poco: lo justo para que
   se note que la pagina se monta, sin hacer esperar a nadie. */
:is(.store-workspace, .app-shell) :is(.workspace-products, .welcome-grid) > * {
    animation: ui-rise .36s var(--ui-ease) both;
}
:is(.store-workspace, .app-shell) :is(.workspace-products, .welcome-grid) > *:nth-child(1) { animation-delay: 0ms; }
:is(.store-workspace, .app-shell) :is(.workspace-products, .welcome-grid) > *:nth-child(2) { animation-delay: 24ms; }
:is(.store-workspace, .app-shell) :is(.workspace-products, .welcome-grid) > *:nth-child(3) { animation-delay: 48ms; }
:is(.store-workspace, .app-shell) :is(.workspace-products, .welcome-grid) > *:nth-child(4) { animation-delay: 72ms; }
:is(.store-workspace, .app-shell) :is(.workspace-products, .welcome-grid) > *:nth-child(5) { animation-delay: 90ms; }
:is(.store-workspace, .app-shell) :is(.workspace-products, .welcome-grid) > *:nth-child(n+6) { animation-delay: 105ms; }

/* =====================================================================
   12 · Tarjeta de combo

   La franja de la portada es ancha y baja, y con tres fichas de 63px
   centradas quedaban perdidas en 659px de tarjeta. Un poco mas de alto
   les da presencia sin alargar la tarjeta de forma apreciable.
   ===================================================================== */

@media (min-width: 601px) {
    :is(.store-workspace, .app-shell) .compact-combos .combo-card-media { height: 116px; }
}

/* =====================================================================
   13 · Inicio del cliente · banda de estado

   Recomposicion, no maquillaje. Antes lo primero que se veia era un
   cartel con una ilustracion y una frase intercambiable, y a la derecha
   una columna con cinco cajas apiladas que moria a media pagina.

   Ahora arriba va lo unico que le importa a quien vuelve —cuanto le queda
   y que se le acaba— y el catalogo se queda con el ancho entero.
   ===================================================================== */

.home-state {
    position: relative;
    display: grid;
    gap: clamp(20px, 3vw, 34px);
    padding: clamp(22px, 3vw, 34px);
    margin-bottom: 14px;
    border: 1px solid var(--border);
    border-radius: var(--ui-radius-lg, 18px);
    background:
        radial-gradient(120% 130% at 0% 0%, rgba(var(--primary-rgb), .14), transparent 58%),
        var(--surface);
    overflow: hidden;
}

/* Una linea de luz arriba, como el resto de superficies levantadas. */
.home-state::after {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 1px;
    margin-inline: 14px;
    background: linear-gradient(90deg, transparent, rgba(var(--text-rgb), .1), transparent);
}
[data-light="1"] .home-state::after { display: none; }

.home-state-main { min-width: 0; }

.home-kicker {
    display: block;
    margin-bottom: 9px;
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--faint);
}

.store-workspace .home-state h1 {
    margin: 0;
    font-family: var(--font-display, inherit);
    font-size: clamp(1.8rem, 1.4rem + 1.6vw, 2.6rem);
    line-height: 1.04;
    letter-spacing: -.035em;
}

.home-lede {
    margin: 12px 0 0;
    max-width: 44ch;
    font-size: 1rem;
    line-height: 1.6;
    color: var(--text-2);
}

/* ---- El saldo: la cifra manda, la etiqueta acompana */
.home-balance { margin-top: clamp(18px, 2.4vw, 26px); }
.home-balance > span {
    display: block;
    margin-bottom: 3px;
    font-size: .82rem;
    color: var(--muted);
}
.home-balance > b {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-family: var(--font-display, inherit);
    font-size: clamp(2.2rem, 1.7rem + 2.2vw, 3.1rem);
    font-weight: 700;
    letter-spacing: -.045em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}
.home-balance > b small {
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .08em;
    color: var(--faint);
}

.home-state-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: clamp(16px, 2vw, 22px);
}

/* ---- El lado derecho: lo que se acaba, o como se compra */
.home-state-side {
    display: flex;
    flex-direction: column;
    gap: 13px;
    padding: clamp(16px, 2vw, 20px);
    border: 1px solid var(--border);
    border-radius: var(--ui-radius, 12px);
    background: rgba(var(--bg-rgb), .45);
}

.home-side-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .76rem;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--faint);
}
.home-side-head .ui-icon { width: 15px; height: 15px; color: var(--primary); }

.home-expiring { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.home-expiring li + li { border-top: 1px solid var(--line-soft, var(--border)); }
.home-expiring a {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 9px 0;
    color: var(--text-2);
}
.home-expiring a:hover { color: var(--text); }
.home-expiring-name {
    min-width: 0;
    font-size: .92rem;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.home-expiring-when {
    flex: none;
    font-size: .82rem;
    font-variant-numeric: tabular-nums;
    color: var(--muted);
}
/* Lo que se acaba esta semana se dice en el color de aviso, no solo con
   el numero: es la diferencia entre informar y avisar. */
.home-expiring-when.is-soon { color: var(--warning); font-weight: 600; }

.home-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
.home-steps li { display: flex; align-items: baseline; gap: 11px; font-size: .92rem; color: var(--text-2); }
.home-steps b {
    flex: none;
    font-size: .78rem;
    font-weight: 700;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
}

.home-points { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.home-points li {
    position: relative;
    padding-left: 22px;
    font-size: .92rem;
    color: var(--text-2);
}
.home-points li::before {
    content: "";
    position: absolute;
    left: 0;
    top: .42em;
    width: 11px; height: 6px;
    border-left: 2px solid var(--primary);
    border-bottom: 2px solid var(--primary);
    transform: rotate(-45deg);
}

.home-side-link {
    margin-top: auto;
    padding-top: 4px;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: .88rem;
    font-weight: 600;
    color: var(--primary);
}
.home-side-link .ui-icon { width: 14px; height: 14px; transition: transform var(--ui-quick, .13s) var(--ui-ease, ease); }
.home-side-link:hover .ui-icon { transform: translateX(3px); }

/* ---- Ayuda al pie: una linea, no dos cajas en una columna */
.home-help {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
    gap: 12px;
    margin-top: clamp(26px, 4vw, 40px);
}
.home-help a {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 18px;
    border: 1px solid var(--border);
    border-radius: var(--ui-radius, 12px);
    background: var(--surface);
    color: var(--text);
    transition: border-color var(--ui-quick, .13s) var(--ui-ease, ease),
                transform var(--ui-quick, .13s) var(--ui-ease, ease);
}
.home-help a:hover { border-color: rgba(var(--primary-rgb), .45); transform: translateY(-1px); }
.home-help a > .ui-icon:first-child { flex: none; width: 20px; height: 20px; color: var(--primary); }
.home-help a > .ui-icon:last-child { flex: none; width: 15px; height: 15px; color: var(--faint); margin-left: auto; }
.home-help span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.home-help b { font-size: .95rem; font-weight: 600; }
.home-help small { font-size: .84rem; line-height: 1.45; color: var(--muted); }

/* ---- Reparto */

@media (min-width: 861px) {
    /* Dos tercios para el estado, uno para lo que se acaba. */
    .home-state { grid-template-columns: minmax(0, 1.4fr) minmax(300px, .9fr); align-items: stretch; }
}

@media (max-width: 600px) {
    .home-state { padding: 18px; }
    .home-state-actions .btn { flex: 1; }
}

/* ---- Ajustes que trae el catalogo al ocupar el ancho entero ---------- */

/* La regla que anula el margen del catalogo existe para la pagina de
   catalogo, donde es la primera seccion. En el inicio no lo es: va debajo
   de los destacados y necesita su aire. */
:is(.store-workspace) .is-landing .catalog-section { margin-top: clamp(26px, 3vw, 38px); }

/* Con el ancho entero caben cuatro destacados en vez de dos enormes. */
@media (min-width: 1100px) {
    :is(.store-workspace) .is-landing .featured-track { grid-auto-columns: calc(25% - 9px); }
}
@media (min-width: 700px) and (max-width: 1099px) {
    :is(.store-workspace) .is-landing .featured-track { grid-auto-columns: calc(33.333% - 8px); }
}

/* ---- Combos en rejilla: que uno solo no se estire ------------------- */

/* La variante compacta repartia el espacio en dos columnas fijas, asi que
   un unico combo se quedaba con 742px: una tarjeta enorme con tres fichas
   pequenas flotando en medio. Con auto-fill cada tarjeta ocupa una pista
   de ancho normal y las pistas que sobran se quedan vacias, que es
   justamente lo que debe pasar. */
@media (min-width: 701px) {
    :is(.store-workspace) .compact-combos {
        grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
    }
}

/* =====================================================================
   14 · Catalogo

   Un titulo en vez de dos, una barra de filtros que se queda pegada al
   bajar, y los descuentos por cantidad a la vista en vez de escondidos
   detras de un desplegable.
   ===================================================================== */

.catalog-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 18px;
    flex-wrap: wrap;
    margin-bottom: clamp(16px, 2vw, 22px);
}

.catalog-head-text { min-width: 0; }

.store-workspace .catalog-head h1 {
    margin: 0;
    font-family: var(--font-display, inherit);
    font-size: clamp(1.9rem, 1.5rem + 1.6vw, 2.7rem);
    line-height: 1.03;
    letter-spacing: -.04em;
}
.store-workspace .catalog-head p {
    margin: 8px 0 0;
    font-size: .98rem;
    color: var(--muted);
}

/* Cuando filtras, el subtitulo se convierte en la salida: saber donde
   estas sirve de poco si no ves como volver. */
.catalog-back {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-top: 9px;
    font-size: .9rem;
    font-weight: 600;
    color: var(--primary);
}
.catalog-back .ui-icon {
    width: 14px; height: 14px;
    transform: rotate(180deg);
    transition: transform var(--ui-quick, .13s) var(--ui-ease, ease);
}
.catalog-back:hover .ui-icon { transform: rotate(180deg) translateX(3px); }

.catalog-count {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    flex: none;
    padding: 7px 13px;
    border: 1px solid var(--border);
    border-radius: var(--ui-radius-pill, 999px);
    background: var(--surface);
    font-size: .84rem;
    color: var(--muted);
}
.catalog-count b {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

/* ---- La barra de filtros ------------------------------------------- */

.catalog-toolbar.is-sticky {
    position: sticky;
    top: var(--topbar-h, 60px);
    z-index: 12;
    margin-inline: calc(var(--gutter, 30px) * -1);
    padding: 12px var(--gutter, 30px);
    /* Fondo opaco por debajo y difuminado por encima: al pasar la rejilla
       por detras, sin esto se lee la letra de los productos a traves. */
    background: rgba(var(--bg-rgb), .86);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid transparent;
    transition: border-color var(--ui-quick, .13s) var(--ui-ease, ease);
}

/* Una linea aparece solo cuando la barra se ha despegado del titulo, para
   que no dibuje un borde flotando en medio de la nada. */
.catalog-toolbar.is-sticky:not(:first-child) { border-bottom-color: var(--border); }

/* ---- Descuentos por cantidad, en una linea ------------------------- */

.volume-line {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin: 14px 0 18px;
    padding: 11px 15px;
    border: 1px solid rgba(var(--primary-rgb), .26);
    border-radius: var(--ui-radius, 12px);
    background: rgba(var(--primary-rgb), .07);
    font-size: .9rem;
}
.volume-line > .ui-icon { flex: none; width: 16px; height: 16px; color: var(--primary); }
.volume-line > b { font-weight: 650; color: var(--text); }

.volume-line-steps { display: flex; flex-wrap: wrap; gap: 7px; margin-left: auto; }
.volume-line-steps > span {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 3px 10px;
    border-radius: 999px;
    background: rgba(var(--bg-rgb), .5);
    font-size: .82rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}
.volume-line-steps > span > b { font-weight: 700; color: var(--primary); }

@media (max-width: 700px) {
    .volume-line { gap: 8px; padding: 11px 13px; }
    .volume-line-steps { margin-left: 0; width: 100%; }
    .catalog-toolbar.is-sticky { margin-inline: calc(var(--gutter, 16px) * -1); padding-inline: var(--gutter, 16px); }
}

/* =====================================================================
   15 · Movil · la tienda en un telefono

   Tres problemas reales, no de gusto:

   1. La primera pantalla era toda informacion. Habia que pasar el saludo,
      el saldo, dos botones, tres vencimientos, tres garantias y el
      buscador antes de ver un solo producto. En una tienda, eso esta al
      reves.
   2. El buscador colgaba a media pagina pegado a otra caja.
   3. El menu de abajo era una tira plana con un rectangulo relleno.
   ===================================================================== */

@media (max-width: 700px) {

    /* ---- El buscador, lo primero y con cuerpo ---------------------- */

    /* Ahora abre la pagina, asi que merece tamano de dedo y que el icono
       viva dentro del campo, no suelto al lado. */
    .store-workspace .mobile-search {
        display: flex;
        align-items: center;
        gap: 10px;
        height: 48px;
        margin: 0 0 16px;
        padding: 0 6px 0 14px;
        border: 1px solid var(--border-2);
        border-radius: 999px;
        background: var(--surface);
        transition: border-color var(--ui-quick, .13s) var(--ui-ease, ease),
                    box-shadow var(--ui-quick, .13s) var(--ui-ease, ease);
    }
    .store-workspace .mobile-search:focus-within {
        border-color: var(--primary);
        box-shadow: 0 0 0 3px var(--focus-ring, rgba(var(--primary-rgb), .3));
    }
    .store-workspace .mobile-search > .ui-icon { width: 18px; height: 18px; color: var(--faint); flex: none; }
    .store-workspace .mobile-search input {
        flex: 1;
        min-width: 0;
        height: 100%;
        border: 0;
        background: none;
        box-shadow: none;
        padding: 0;
        font-size: .95rem;
    }
    .store-workspace .mobile-search input:focus { box-shadow: none; }
    .store-workspace .mobile-search button {
        display: grid;
        place-items: center;
        width: 36px; height: 36px;
        flex: none;
        border: 0;
        border-radius: 50%;
        background: var(--primary);
        color: var(--on-primary);
        cursor: pointer;
    }
    .store-workspace .mobile-search button .ui-icon { width: 17px; height: 17px; }

    /* ---- La banda de estado, al grano ------------------------------ */

    .home-state { padding: 16px; gap: 14px; margin-bottom: 12px; }
    .store-workspace .home-state h1 { font-size: 1.55rem; }
    /* El rotulo de arriba es decoracion: en un telefono cuesta 24px de
       altura para no decir nada que el saludo no diga ya. */
    .home-kicker { display: none; }

    /* Saldo y accion en la misma fila: apilados se comian media pantalla
       para decir dos cosas. */
    .home-balance { margin-top: 14px; }
    .home-balance > b { font-size: 2rem; }
    .home-state-actions { margin-top: 12px; gap: 8px; }
    .home-state-actions .btn { flex: 1; min-height: 46px; font-size: .9rem; }

    .home-state-side { padding: 14px; gap: 10px; }
    .home-side-head { font-size: .68rem; }

    /* Dos vencimientos bastan para avisar; el tercero solo alargaba la
       pantalla. El enlace de abajo lleva a todos. */
    .home-expiring li:nth-child(n+3) { display: none; }
    .home-expiring a { padding: 8px 0; }
    .home-expiring-name { font-size: .88rem; }

    /* ---- Las garantias, una tira que se desliza -------------------- */

    /* Apiladas eran tres lineas de altura muerta justo antes del producto.
       En una fila que se desliza dicen lo mismo en un tercio del sitio. */
    .store-workspace .assurance-strip {
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        gap: 8px;
        overflow-x: auto;
        scrollbar-width: none;
        padding: 0;
        margin-bottom: 18px;
        border: 0;
        background: none;
    }
    .store-workspace .assurance-strip::-webkit-scrollbar { display: none; }
    .store-workspace .assurance-strip span {
        flex: none;
        gap: 7px;
        padding: 8px 13px;
        border: 1px solid var(--border);
        border-radius: 999px;
        background: var(--surface);
        font-size: .8rem;
        white-space: nowrap;
    }

    /* ---- Cabecera del catalogo ------------------------------------- */

    .catalog-head { align-items: center; margin-bottom: 14px; }
    .store-workspace .catalog-head h1 { font-size: 1.75rem; }
    .store-workspace .catalog-head p { font-size: .9rem; margin-top: 5px; }
    .catalog-count { padding: 5px 11px; font-size: .78rem; }
}

/* =====================================================================
   16 · Movil · el menu de abajo

   Deja de ser una tira pegada al borde. Flota, se despega de los lados y
   marca donde estas con una pastilla, no con un rectangulo relleno.
   ===================================================================== */

@media (max-width: 600px) {
    .store-workspace .mobile-dock {
        left: 10px;
        right: 10px;
        bottom: calc(10px + env(safe-area-inset-bottom, 0px));
        min-height: 62px;
        padding: 7px 6px;
        border: 1px solid var(--border-2);
        border-radius: 20px;
        /* Translucido con desenfoque: se ve que hay pagina debajo, que es
           lo que dice que la barra flota. */
        background: rgba(var(--surface-rgb), .82);
        backdrop-filter: blur(18px) saturate(140%);
        -webkit-backdrop-filter: blur(18px) saturate(140%);
        box-shadow: 0 10px 30px rgba(0, 0, 0, .4), 0 1px 0 rgba(var(--text-rgb), .06) inset;
    }

    .store-workspace .mobile-dock a,
    .store-workspace .mobile-dock button {
        position: relative;
        gap: 4px;
        padding: 6px 2px;
        border-radius: 14px;
        font-size: .68rem;
        font-weight: 600;
        letter-spacing: .01em;
        transition: color var(--ui-quick, .13s) var(--ui-ease, ease);
    }
    .store-workspace .mobile-dock .ui-icon {
        width: 21px; height: 21px;
        transition: transform var(--ui-quick, .13s) var(--ui-ease, ease);
    }

    /* La pagina en la que estas: el icono sube un pelo, toma el color de
       la tienda y le aparece una pastilla detras. Sin fondo macizo, que
       recortaba un bloque en medio de la barra. */
    .store-workspace .mobile-dock .active {
        color: var(--primary);
        background: none;
    }
    .store-workspace .mobile-dock .active .ui-icon { transform: translateY(-1px); }
    .store-workspace .mobile-dock .active::before {
        content: "";
        position: absolute;
        top: 2px;
        left: 50%;
        width: 30px;
        height: 30px;
        transform: translateX(-50%);
        border-radius: 11px;
        background: rgba(var(--primary-rgb), .15);
    }

    /* Un punto sobre el icono cuando hay algo sin leer. El numero no cabe
       aqui, pero la senal si. */
    .store-workspace .mobile-dock [data-badge]::after {
        content: "";
        position: absolute;
        top: 7px;
        left: calc(50% + 8px);
        width: 7px;
        height: 7px;
        border-radius: 50%;
        background: var(--primary);
        box-shadow: 0 0 0 2px var(--surface);
    }

    /* El pie deja sitio a la barra flotante, que ahora es mas alta. */
    .store-workspace .workspace-footer { padding-bottom: 104px; }
    .builder .wrap { padding-bottom: 176px; }
}

/* ---- Movil: la banda cede el sitio al producto ---------------------- */

@media (max-width: 700px) {
    /*
     * En una pantalla de telefono la lista de vencimientos solo se gana su
     * sitio si algo se acaba de verdad. Si no hay nada urgente se retira, y
     * lo mismo los pasos y las razones: son utiles, pero no por delante de
     * lo que se vende.
     *
     * `is-soon` lo pone el servidor cuando quedan siete dias o menos.
     */
    .home-state-side:not(:has(.is-soon)) { display: none; }

    /* Y si lo hay, solo eso: lo que vence en un mes no es un aviso. */
    .home-expiring li:not(:has(.is-soon)) { display: none; }
}

/* =====================================================================
   17 · Carruseles: sitio para que la tarjeta se levante

   Una caja con overflow-x: auto tambien recorta en vertical -- la norma
   dice que si un eje deja de ser visible, el otro pasa a auto. Asi que en
   las filas que se deslizan, los 3px que sube una tarjeta al pasar por
   encima quedaban fuera de la caja y se los comia el recorte: el borde
   superior aparecia cortado.

   La solucion no es quitar el movimiento, es darle sitio: relleno arriba
   y abajo, y margen negativo del mismo tamano para que la maquetacion se
   quede exactamente donde estaba.
   ===================================================================== */

:is(.store-workspace) .featured-track {
    padding-block: 10px;
    margin-block: -10px;
}

/* Los combos se levantan mas y ademas arrastran sombra. */
:is(.store-workspace) .compact-combos {
    padding-block: 16px;
    margin-block: -16px;
}

/* El relleno lateral que ya traian para sangrar al borde en movil se
   respeta: aqui solo se toca el eje vertical. */

/* =====================================================================
   18 · Tarjeta de producto en movil

   Median 166 de ancho por 366 de alto: casi 1 a 2,2. Una columna de
   tarjetas alargadas se recorre mal y cabe muy poco en pantalla.

   Parte de esa altura la puse yo al separar categoria y disponibilidad en
   dos lineas para que dejaran de pisarse. Arreglo el solape de otra
   manera: quitando lo que ya se dice en otro sitio.
   ===================================================================== */

.product-plans { display: none; }

@media (max-width: 600px) {

    /* ---- La imagen manda ------------------------------------------- */

    /* Cuatro tercios en vez de una tira: en una tarjeta estrecha la
       caratula es lo que identifica el producto de un vistazo. */
    .store-workspace .workspace-product .product-img {
        height: auto;
        aspect-ratio: 4 / 3;
    }

    /* ---- Fuera lo que se repite ------------------------------------ */

    /* La sobrelinea llevaba categoria y disponibilidad. La categoria ya la
       sabes: o filtraste por ella o estas viendo todo. Y "Agotado" ya se
       dice encima de la imagen, mas visible. */
    .store-workspace .workspace-product .product-overline { display: none; }

    /* Las fichas de plan se cambian por una linea. */
    .store-workspace .product-variant-chips { display: none; }
    .store-workspace .product-plans {
        display: block;
        margin-bottom: 9px;
        font-size: .78rem;
        font-weight: 500;
        color: var(--muted);
    }

    /* ---- Lo que queda, con aire --------------------------------------- */

    .store-workspace .workspace-product .product-body { padding: 11px 11px 12px; }

    .store-workspace .workspace-product h3 {
        font-size: .88rem;
        font-weight: 600;
        line-height: 1.32;
        margin-bottom: 7px;
        /* Dos lineas y punto: un nombre largo no debe estirar su tarjeta
           mas que las de al lado. */
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        overflow: hidden;
    }

    .store-workspace .workspace-product .product-subline {
        font-size: .78rem;
        min-height: 0;
        margin-bottom: 9px;
    }

    /* El precio cierra la tarjeta y es lo unico que crece. */
    .store-workspace .workspace-product .product-meta { padding-top: 9px; }
    .store-workspace .workspace-product .price { font-size: 1.12rem; font-weight: 700; }
    .store-workspace .product-price-stack > small { font-size: .68rem; letter-spacing: .1em; }

    /* ---- El sello de agotado, mas presente ------------------------- */

    /* Es la unica pieza que se queda sin su linea de texto, asi que tiene
       que leerse sola sobre la imagen. */
    .store-workspace .product-soldout {
        padding: 5px 12px;
        font-size: .76rem;
        font-weight: 700;
        letter-spacing: .02em;
        backdrop-filter: blur(6px);
    }

    /* ---- Un poco mas de separacion entre tarjetas ------------------ */
    .store-workspace .workspace-products,
    .store-workspace .catalog-only .workspace-products { gap: 12px; }
}

/* En pantallas muy estrechas dos columnas dejan tarjetas de 150px: el
   nombre cabe justo y el precio manda igual. */
@media (max-width: 360px) {
    .store-workspace .workspace-product h3 { font-size: .84rem; }
    .store-workspace .workspace-product .price { font-size: 1.05rem; }
}
