Files
Autoparts-DB/pos/templates/catalog.html
consultoria-as 380698258a feat: agregar design system completo con 2 temas (Industrial + Moderno)
- Login: PIN pad con seleccion de usuario + auth real via API
- Catalogo: grid de productos con sidebar nav y filtros
- POS: layout split con numpad y area de venta
- tokens.css: sistema completo de CSS variables (colores, tipografia, espaciado)
- 2 temas: Industrial Robusto (dark/amber) y Tecnico Moderno (light/orange)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 06:22:46 +00:00

2074 lines
71 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="es" data-theme="industrial">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Catálogo — Nexus Autoparts POS</title>
<link rel="stylesheet" href="/pos/static/css/tokens.css" />
<style>
/* =========================================================================
BASE RESET & SHELL
========================================================================= */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
body {
font-family: var(--font-body);
font-size: var(--text-body);
color: var(--color-text-primary);
background-color: var(--color-bg-base);
transition: background-color var(--duration-normal) var(--ease-in-out),
color var(--duration-normal) var(--ease-in-out);
overflow: hidden;
}
[data-theme="modern"] body,
[data-theme="modern"].body-shell {
background-color: var(--color-bg-base);
background-image: radial-gradient(
circle,
var(--dot-grid-color) 1px,
transparent 1px
);
background-size: var(--dot-grid-size) var(--dot-grid-size);
}
/* =========================================================================
THEME SWITCHER BAR
========================================================================= */
.theme-bar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: var(--z-toast);
display: flex;
align-items: center;
justify-content: flex-end;
gap: var(--space-2);
padding: var(--space-2) var(--space-4);
background: var(--color-bg-overlay);
border-bottom: 1px solid var(--color-border);
backdrop-filter: blur(8px);
height: 36px;
}
.theme-bar__label {
font-size: var(--text-caption);
color: var(--color-text-muted);
font-family: var(--font-body);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
}
.theme-btn {
display: inline-flex;
align-items: center;
gap: var(--space-1);
padding: 3px var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius-full);
background: transparent;
color: var(--color-text-secondary);
font-family: var(--font-body);
font-size: var(--text-caption);
font-weight: var(--font-weight-semibold);
cursor: pointer;
transition: var(--transition-fast);
}
.theme-btn:hover {
border-color: var(--color-primary);
color: var(--color-primary);
}
.theme-btn.is-active {
background: var(--color-primary);
border-color: var(--color-primary);
color: var(--color-text-inverse);
}
/* =========================================================================
APP LAYOUT
========================================================================= */
.app-shell {
display: flex;
height: 100vh;
padding-top: 36px; /* theme bar height */
}
/* =========================================================================
SIDEBAR
========================================================================= */
.sidebar {
width: 260px;
flex-shrink: 0;
display: flex;
flex-direction: column;
background: var(--color-bg-elevated);
border-right: 1px solid var(--color-border);
overflow-y: auto;
transition: var(--transition-normal);
}
[data-theme="industrial"] .sidebar {
border-right-color: var(--color-border);
}
/* ---- Brand ---- */
.sidebar__brand {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-5) var(--space-5) var(--space-4);
border-bottom: 1px solid var(--color-border);
flex-shrink: 0;
}
.brand-logo {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-primary);
color: var(--color-text-inverse);
font-family: var(--font-heading);
font-weight: var(--heading-weight-primary);
font-size: 1.375rem;
letter-spacing: var(--tracking-tight);
flex-shrink: 0;
}
[data-theme="industrial"] .brand-logo {
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
border-radius: 0;
}
[data-theme="modern"] .brand-logo {
border-radius: var(--radius-md);
}
.brand-name {
display: flex;
flex-direction: column;
line-height: 1;
}
.brand-name__primary {
font-family: var(--font-heading);
font-weight: var(--heading-weight-primary);
font-size: 1.125rem;
letter-spacing: var(--tracking-wide);
color: var(--color-text-primary);
text-transform: uppercase;
}
.brand-name__sub {
font-family: var(--font-body);
font-size: var(--text-caption);
color: var(--color-text-muted);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
margin-top: 2px;
}
/* ---- Navigation ---- */
.sidebar__nav {
flex: 1;
padding: var(--space-3) 0;
}
.nav-section-label {
padding: var(--space-3) var(--space-5) var(--space-1);
font-size: var(--text-caption);
font-family: var(--font-body);
font-weight: var(--font-weight-semibold);
color: var(--color-text-muted);
letter-spacing: var(--tracking-widest);
text-transform: uppercase;
}
.nav-item {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-2) var(--space-5);
color: var(--color-text-secondary);
font-family: var(--font-body);
font-size: var(--text-body-sm);
font-weight: var(--font-weight-regular);
text-decoration: none;
cursor: pointer;
border: none;
background: none;
width: 100%;
text-align: left;
transition: var(--transition-fast);
border-left: 3px solid transparent;
position: relative;
}
.nav-item:hover {
background: var(--color-primary-muted);
color: var(--color-text-primary);
border-left-color: var(--color-primary);
}
.nav-item.is-active {
background: var(--color-primary-muted);
color: var(--color-primary);
font-weight: var(--font-weight-semibold);
border-left-color: var(--color-primary);
}
[data-theme="industrial"] .nav-item.is-active {
background: rgba(245, 166, 35, 0.12);
}
.nav-item__icon {
width: 18px;
height: 18px;
opacity: 0.75;
flex-shrink: 0;
}
.nav-item.is-active .nav-item__icon,
.nav-item:hover .nav-item__icon {
opacity: 1;
}
.nav-item__badge {
margin-left: auto;
background: var(--color-primary);
color: var(--color-text-inverse);
font-size: 10px;
font-weight: var(--font-weight-bold);
padding: 1px 6px;
border-radius: var(--radius-full);
line-height: 1.4;
}
/* ---- User profile ---- */
.sidebar__profile {
padding: var(--space-4) var(--space-5);
border-top: 1px solid var(--color-border);
display: flex;
align-items: center;
gap: var(--space-3);
flex-shrink: 0;
}
.profile-avatar {
width: 36px;
height: 36px;
background: var(--color-primary);
color: var(--color-text-inverse);
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-heading);
font-weight: var(--heading-weight-primary);
font-size: 0.9rem;
flex-shrink: 0;
}
[data-theme="industrial"] .profile-avatar {
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
}
[data-theme="modern"] .profile-avatar {
border-radius: var(--radius-full);
}
.profile-info {
flex: 1;
min-width: 0;
}
.profile-info__name {
font-size: var(--text-body-sm);
font-weight: var(--font-weight-semibold);
color: var(--color-text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.profile-info__role {
font-size: var(--text-caption);
color: var(--color-text-muted);
}
.profile-btn {
background: none;
border: none;
color: var(--color-text-muted);
cursor: pointer;
padding: var(--space-1);
border-radius: var(--radius-sm);
transition: var(--transition-fast);
flex-shrink: 0;
}
.profile-btn:hover {
color: var(--color-text-primary);
background: var(--color-primary-muted);
}
/* =========================================================================
MAIN CONTENT AREA
========================================================================= */
.main-content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
min-width: 0;
}
/* ---- Header bar ---- */
.content-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 var(--space-6);
height: 56px;
flex-shrink: 0;
background: var(--color-bg-elevated);
border-bottom: 1px solid var(--color-border);
}
.breadcrumb {
display: flex;
align-items: center;
gap: var(--space-2);
font-size: var(--text-body-sm);
color: var(--color-text-muted);
}
.breadcrumb__link {
color: var(--color-text-muted);
text-decoration: none;
transition: var(--transition-fast);
}
.breadcrumb__link:hover {
color: var(--color-primary);
}
.breadcrumb__sep {
color: var(--color-text-disabled);
}
.breadcrumb__current {
color: var(--color-text-primary);
font-weight: var(--font-weight-semibold);
}
.header-actions {
display: flex;
align-items: center;
gap: var(--space-3);
}
.icon-btn {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
background: none;
border: 1px solid var(--color-border);
color: var(--color-text-secondary);
cursor: pointer;
transition: var(--transition-fast);
border-radius: var(--radius-md);
position: relative;
}
[data-theme="industrial"] .icon-btn {
border-radius: 0;
}
.icon-btn:hover {
border-color: var(--color-primary);
color: var(--color-primary);
}
.icon-btn .notif-dot {
position: absolute;
top: 6px;
right: 6px;
width: 7px;
height: 7px;
background: var(--color-error);
border-radius: var(--radius-full);
border: 1px solid var(--color-bg-elevated);
}
/* =========================================================================
SCROLLABLE PAGE BODY
========================================================================= */
.page-body {
flex: 1;
overflow-y: auto;
padding: var(--space-6);
display: flex;
flex-direction: column;
gap: var(--space-5);
}
[data-theme="modern"] .page-body {
background-color: var(--color-bg-base);
background-image: radial-gradient(
circle,
var(--dot-grid-color) 1px,
transparent 1px
);
background-size: var(--dot-grid-size) var(--dot-grid-size);
}
/* =========================================================================
SEARCH SECTION
========================================================================= */
.search-panel {
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
padding: var(--space-5);
box-shadow: var(--shadow-sm);
}
[data-theme="industrial"] .search-panel {
clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%);
border-radius: 0;
}
[data-theme="modern"] .search-panel {
border-radius: var(--radius-lg);
}
.search-panel__title {
font-family: var(--font-heading);
font-weight: var(--heading-weight-primary);
font-size: var(--text-h5);
color: var(--color-text-primary);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
margin-bottom: var(--space-4);
display: flex;
align-items: center;
gap: var(--space-2);
}
[data-theme="industrial"] .search-panel__title {
color: var(--color-primary);
}
.search-panel__title svg {
color: var(--color-primary);
}
.vehicle-search-row {
display: grid;
grid-template-columns: 1fr 1fr 1fr auto;
gap: var(--space-3);
align-items: end;
}
.form-group {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.form-label {
font-size: var(--text-caption);
font-weight: var(--font-weight-semibold);
color: var(--color-text-muted);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
}
.form-select,
.form-input {
width: 100%;
padding: var(--space-2) var(--space-3);
background: var(--color-bg-overlay);
border: 1px solid var(--color-border);
color: var(--color-text-primary);
font-family: var(--font-body);
font-size: var(--text-body-sm);
outline: none;
transition: var(--transition-fast);
appearance: none;
-webkit-appearance: none;
height: 40px;
}
[data-theme="industrial"] .form-select,
[data-theme="industrial"] .form-input {
border-radius: 0;
}
[data-theme="modern"] .form-select,
[data-theme="modern"] .form-input {
border-radius: var(--radius-md);
}
.form-select:focus,
.form-input:focus {
border-color: var(--color-border-focus);
box-shadow: var(--shadow-focus);
}
.form-select {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888888' stroke-width='2.5'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 10px center;
padding-right: var(--space-8);
cursor: pointer;
}
.form-select option {
background: var(--color-bg-overlay);
color: var(--color-text-primary);
}
/* Part search row */
.part-search-row {
display: grid;
grid-template-columns: 1fr auto;
gap: var(--space-3);
align-items: end;
margin-top: var(--space-3);
}
.form-input-with-icon {
position: relative;
}
.form-input-with-icon svg {
position: absolute;
left: 10px;
top: 50%;
transform: translateY(-50%);
color: var(--color-text-muted);
pointer-events: none;
}
.form-input-with-icon .form-input {
padding-left: var(--space-8);
}
/* ---- Buttons ---- */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-2);
padding: 0 var(--space-5);
height: 40px;
font-family: var(--font-body);
font-size: var(--text-body-sm);
font-weight: var(--font-weight-semibold);
border: 1px solid transparent;
cursor: pointer;
transition: var(--transition-fast);
white-space: nowrap;
text-decoration: none;
letter-spacing: var(--tracking-wide);
}
[data-theme="industrial"] .btn {
border-radius: 0;
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
text-transform: uppercase;
}
[data-theme="modern"] .btn {
border-radius: var(--radius-md);
}
.btn-primary {
background: var(--btn-primary-bg);
color: var(--btn-primary-text);
border-color: var(--btn-primary-border);
}
.btn-primary:hover {
background: var(--btn-primary-bg-hover);
}
.btn-primary:active {
background: var(--btn-primary-bg-active);
}
.btn-secondary {
background: var(--btn-secondary-bg);
color: var(--btn-secondary-text);
border-color: var(--btn-secondary-border);
}
.btn-secondary:hover {
background: var(--btn-secondary-bg-hover);
}
.btn-ghost {
background: var(--btn-ghost-bg);
color: var(--btn-ghost-text);
border-color: var(--btn-ghost-border);
}
.btn-ghost:hover {
border-color: var(--color-primary);
color: var(--color-primary);
}
/* =========================================================================
RESULTS BAR
========================================================================= */
.results-bar {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: var(--space-3);
}
.results-count {
font-family: var(--font-heading);
font-weight: var(--heading-weight-secondary);
font-size: var(--text-h5);
color: var(--color-text-primary);
letter-spacing: var(--tracking-snug);
}
.results-count strong {
color: var(--color-primary);
font-weight: var(--heading-weight-primary);
}
/* =========================================================================
FILTER CHIPS
========================================================================= */
.filters-row {
display: flex;
align-items: center;
gap: var(--space-2);
flex-wrap: wrap;
}
.filters-label {
font-size: var(--text-caption);
color: var(--color-text-muted);
font-weight: var(--font-weight-semibold);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
flex-shrink: 0;
}
.chip {
display: inline-flex;
align-items: center;
gap: var(--space-1);
padding: 4px var(--space-3);
border: 1px solid var(--color-border);
background: transparent;
color: var(--color-text-secondary);
font-family: var(--font-body);
font-size: var(--text-caption);
font-weight: var(--font-weight-semibold);
cursor: pointer;
transition: var(--transition-fast);
user-select: none;
}
[data-theme="industrial"] .chip {
border-radius: 0;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
}
[data-theme="modern"] .chip {
border-radius: var(--radius-full);
}
.chip:hover {
border-color: var(--color-primary);
color: var(--color-primary);
background: var(--color-primary-muted);
}
.chip.is-active {
background: var(--color-primary);
border-color: var(--color-primary);
color: var(--color-text-inverse);
}
[data-theme="industrial"] .chip.is-active {
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
}
/* =========================================================================
TOOLBAR (sort + view toggle)
========================================================================= */
.catalog-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-3);
}
.sort-row {
display: flex;
align-items: center;
gap: var(--space-3);
}
.sort-label {
font-size: var(--text-caption);
color: var(--color-text-muted);
font-weight: var(--font-weight-semibold);
text-transform: uppercase;
letter-spacing: var(--tracking-wider);
}
.sort-select {
padding: 4px var(--space-7) 4px var(--space-3);
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
color: var(--color-text-secondary);
font-family: var(--font-body);
font-size: var(--text-caption);
outline: none;
cursor: pointer;
appearance: none;
-webkit-appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%23888888' stroke-width='2.5'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 8px center;
transition: var(--transition-fast);
height: 32px;
}
[data-theme="industrial"] .sort-select {
border-radius: 0;
}
[data-theme="modern"] .sort-select {
border-radius: var(--radius-md);
}
.sort-select:focus {
border-color: var(--color-border-focus);
}
.view-toggle {
display: flex;
border: 1px solid var(--color-border);
overflow: hidden;
}
[data-theme="industrial"] .view-toggle {
border-radius: 0;
}
[data-theme="modern"] .view-toggle {
border-radius: var(--radius-md);
}
.view-btn {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: none;
color: var(--color-text-muted);
cursor: pointer;
transition: var(--transition-fast);
border-right: 1px solid var(--color-border);
}
.view-btn:last-child {
border-right: none;
}
.view-btn:hover {
color: var(--color-primary);
background: var(--color-primary-muted);
}
.view-btn.is-active {
background: var(--color-primary);
color: var(--color-text-inverse);
}
/* =========================================================================
PRODUCT GRID
========================================================================= */
.product-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-4);
}
.product-grid.view-list {
grid-template-columns: 1fr;
}
/* ---- Product Card ---- */
.product-card {
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
display: flex;
flex-direction: column;
transition: var(--transition-normal);
position: relative;
overflow: hidden;
}
[data-theme="industrial"] .product-card {
border-radius: 0;
clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%);
}
[data-theme="modern"] .product-card {
border-radius: var(--radius-lg);
}
.product-card:hover {
border-color: var(--color-primary);
box-shadow: var(--shadow-md);
transform: translateY(-2px);
}
[data-theme="industrial"] .product-card:hover {
box-shadow: 0 4px 16px rgba(245, 166, 35, 0.15), var(--shadow-md);
}
/* List view card overrides */
.view-list .product-card {
flex-direction: row;
align-items: center;
}
[data-theme="industrial"] .view-list .product-card {
clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);
}
.view-list .product-card__image {
width: 100px;
min-width: 100px;
height: 80px;
}
.view-list .product-card__body {
flex: 1;
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
gap: var(--space-4);
}
.view-list .product-card__pricing {
text-align: right;
flex-shrink: 0;
}
.view-list .product-card__compatibility {
grid-column: 1 / -1;
}
/* Card image placeholder */
.product-card__image {
height: 140px;
background: var(--color-bg-overlay);
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid var(--color-border);
flex-shrink: 0;
position: relative;
overflow: hidden;
}
[data-theme="industrial"] .product-card__image {
background: var(--color-surface-2);
}
.product-card__image svg {
color: var(--color-text-disabled);
opacity: 0.5;
}
.product-card__image-label {
position: absolute;
bottom: var(--space-2);
left: var(--space-2);
font-size: 10px;
font-family: var(--font-mono);
color: var(--color-text-muted);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
background: var(--color-bg-elevated);
padding: 1px var(--space-2);
}
[data-theme="industrial"] .product-card__image-label {
border-radius: 0;
border-left: 2px solid var(--color-primary);
}
[data-theme="modern"] .product-card__image-label {
border-radius: var(--radius-sm);
}
/* Card stock badge (on image) */
.stock-badge {
position: absolute;
top: var(--space-2);
right: var(--space-2);
display: flex;
align-items: center;
gap: 4px;
padding: 3px var(--space-2);
font-size: 10px;
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
}
[data-theme="industrial"] .stock-badge {
border-radius: 0;
}
[data-theme="modern"] .stock-badge {
border-radius: var(--radius-full);
}
.stock-badge::before {
content: '';
width: 6px;
height: 6px;
border-radius: var(--radius-full);
flex-shrink: 0;
}
.stock-badge.stock-ok {
background: rgba(34, 197, 94, 0.15);
color: var(--color-success);
border: 1px solid rgba(34, 197, 94, 0.3);
}
.stock-badge.stock-ok::before { background: var(--color-success); }
.stock-badge.stock-low {
background: rgba(234, 179, 8, 0.15);
color: var(--color-warning);
border: 1px solid rgba(234, 179, 8, 0.3);
}
.stock-badge.stock-low::before { background: var(--color-warning); }
.stock-badge.stock-out {
background: rgba(239, 68, 68, 0.15);
color: var(--color-error);
border: 1px solid rgba(239, 68, 68, 0.3);
}
.stock-badge.stock-out::before { background: var(--color-error); }
/* Card body */
.product-card__body {
padding: var(--space-4);
flex: 1;
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.product-card__category {
font-size: 10px;
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-widest);
text-transform: uppercase;
color: var(--color-primary);
}
.product-card__name {
font-family: var(--font-heading);
font-weight: var(--heading-weight-secondary);
font-size: 0.9375rem;
color: var(--color-text-primary);
line-height: 1.3;
letter-spacing: var(--tracking-snug);
}
[data-theme="industrial"] .product-card__name {
text-transform: uppercase;
}
.product-card__oem {
font-family: var(--font-mono);
font-size: var(--text-caption);
color: var(--color-text-muted);
letter-spacing: var(--tracking-wide);
}
.product-card__brand {
font-size: var(--text-caption);
color: var(--color-text-secondary);
display: flex;
align-items: center;
gap: var(--space-1);
}
.product-card__brand-dot {
width: 3px;
height: 3px;
border-radius: var(--radius-full);
background: var(--color-text-disabled);
flex-shrink: 0;
}
.product-card__compatibility {
display: flex;
align-items: center;
gap: var(--space-1);
padding: var(--space-1) var(--space-2);
background: var(--color-primary-muted);
border-left: 2px solid var(--color-primary);
font-size: 10px;
font-family: var(--font-body);
color: var(--color-text-accent);
}
[data-theme="modern"] .product-card__compatibility {
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
/* Card footer */
.product-card__footer {
padding: var(--space-3) var(--space-4);
border-top: 1px solid var(--color-border);
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-3);
flex-shrink: 0;
}
.product-card__pricing {}
.product-card__price {
font-family: var(--font-mono);
font-weight: var(--font-weight-bold);
font-size: 1.1875rem;
color: var(--color-text-primary);
line-height: 1;
}
[data-theme="industrial"] .product-card__price {
color: var(--color-primary);
}
.product-card__price-unit {
font-size: var(--text-caption);
color: var(--color-text-muted);
margin-top: 2px;
}
/* Add button */
.btn-add {
display: inline-flex;
align-items: center;
gap: var(--space-1);
padding: var(--space-1) var(--space-3);
background: var(--btn-primary-bg);
color: var(--btn-primary-text);
font-family: var(--font-body);
font-size: var(--text-caption);
font-weight: var(--font-weight-bold);
border: 1px solid transparent;
cursor: pointer;
transition: var(--transition-fast);
letter-spacing: var(--tracking-wide);
white-space: nowrap;
height: 32px;
}
[data-theme="industrial"] .btn-add {
border-radius: 0;
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
text-transform: uppercase;
}
[data-theme="modern"] .btn-add {
border-radius: var(--radius-md);
}
.btn-add:hover {
background: var(--btn-primary-bg-hover);
}
.btn-add:active {
background: var(--btn-primary-bg-active);
}
/* =========================================================================
PAGINATION
========================================================================= */
.pagination {
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-1);
padding: var(--space-4) 0;
}
.page-item {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
color: var(--color-text-secondary);
font-family: var(--font-body);
font-size: var(--text-body-sm);
font-weight: var(--font-weight-semibold);
cursor: pointer;
transition: var(--transition-fast);
user-select: none;
}
[data-theme="industrial"] .page-item {
border-radius: 0;
font-family: var(--font-mono);
}
[data-theme="modern"] .page-item {
border-radius: var(--radius-md);
}
.page-item:hover:not(.is-active):not(.is-disabled) {
border-color: var(--color-primary);
color: var(--color-primary);
background: var(--color-primary-muted);
}
.page-item.is-active {
background: var(--color-primary);
border-color: var(--color-primary);
color: var(--color-text-inverse);
}
[data-theme="industrial"] .page-item.is-active {
clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
}
.page-item.is-disabled {
opacity: 0.4;
cursor: not-allowed;
}
.page-item--wide {
width: auto;
padding: 0 var(--space-3);
gap: var(--space-1);
}
.page-ellipsis {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
color: var(--color-text-muted);
font-size: var(--text-body-sm);
user-select: none;
}
/* =========================================================================
SCROLLBAR
========================================================================= */
.page-body::-webkit-scrollbar,
.sidebar::-webkit-scrollbar {
width: 6px;
}
.page-body::-webkit-scrollbar-track,
.sidebar::-webkit-scrollbar-track {
background: var(--scrollbar-track);
}
.page-body::-webkit-scrollbar-thumb,
.sidebar::-webkit-scrollbar-thumb {
background-color: var(--scrollbar-thumb);
border-radius: var(--radius-full);
}
.page-body::-webkit-scrollbar-thumb:hover,
.sidebar::-webkit-scrollbar-thumb:hover {
background-color: var(--scrollbar-thumb-hover);
}
/* =========================================================================
INDUSTRIAL THEME — DECORATIVE ACCENTS
========================================================================= */
[data-theme="industrial"] .sidebar__brand::after {
display: none; /* removed, using clip already */
}
[data-theme="industrial"] .content-header {
border-bottom-color: var(--color-border);
position: relative;
}
[data-theme="industrial"] .content-header::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 80px;
height: 2px;
background: var(--color-primary);
}
/* =========================================================================
SIDEBAR TOGGLE (mobile)
========================================================================= */
.sidebar-toggle {
display: none;
width: 36px;
height: 36px;
align-items: center;
justify-content: center;
background: none;
border: 1px solid var(--color-border);
color: var(--color-text-secondary);
cursor: pointer;
transition: var(--transition-fast);
border-radius: var(--radius-md);
}
[data-theme="industrial"] .sidebar-toggle {
border-radius: 0;
}
/* =========================================================================
RESPONSIVE
========================================================================= */
@media (max-width: 1024px) {
.product-grid:not(.view-list) {
grid-template-columns: repeat(2, 1fr);
}
.vehicle-search-row {
grid-template-columns: 1fr 1fr;
}
.vehicle-search-row .form-group:last-child {
grid-column: 1 / -1;
}
}
@media (max-width: 768px) {
.sidebar {
position: fixed;
top: 36px;
left: 0;
bottom: 0;
z-index: var(--z-dropdown);
transform: translateX(-100%);
transition: transform var(--duration-normal) var(--ease-in-out);
}
.sidebar.is-open {
transform: translateX(0);
box-shadow: var(--shadow-xl);
}
.sidebar-toggle {
display: flex;
}
.product-grid:not(.view-list) {
grid-template-columns: repeat(2, 1fr);
}
.vehicle-search-row {
grid-template-columns: 1fr;
}
.vehicle-search-row .form-group:last-child {
grid-column: auto;
}
.part-search-row {
grid-template-columns: 1fr;
}
.catalog-toolbar {
flex-direction: column;
align-items: flex-start;
}
.results-bar {
flex-direction: column;
align-items: flex-start;
}
}
@media (max-width: 480px) {
.product-grid:not(.view-list) {
grid-template-columns: 1fr;
}
.page-body {
padding: var(--space-4);
}
}
/* =========================================================================
OVERLAY (mobile sidebar backdrop)
========================================================================= */
.sidebar-overlay {
display: none;
position: fixed;
inset: 0;
top: 36px;
background: var(--overlay-backdrop);
z-index: calc(var(--z-dropdown) - 1);
backdrop-filter: blur(2px);
}
.sidebar-overlay.is-open {
display: block;
}
</style>
</head>
<body>
<!-- =========================================================================
THEME SWITCHER BAR
========================================================================= -->
<div class="theme-bar" role="toolbar" aria-label="Cambiar tema">
<span class="theme-bar__label">Tema:</span>
<button class="theme-btn is-active" data-theme-switch="industrial" aria-pressed="true">
<!-- gear icon -->
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 2l2.4 1.6L17 3l1 2.6 2.4 1.6-.2 2.8L22 12l-1.8 2 .2 2.8-2.4 1.6-1 2.6-2.6-.2L12 22l-2.4-1.6L7 21l-1-2.6-2.4-1.6.2-2.8L2 12l1.8-2-.2-2.8L6 5.6 7 3l2.6.2z"/><circle cx="12" cy="12" r="3"/></svg>
Industrial
</button>
<button class="theme-btn" data-theme-switch="modern" aria-pressed="false">
<!-- sparkle icon -->
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/></svg>
Moderno
</button>
</div>
<!-- Mobile sidebar overlay -->
<div class="sidebar-overlay" id="sidebarOverlay" role="presentation"></div>
<!-- =========================================================================
APP SHELL
========================================================================= -->
<div class="app-shell">
<!-- =====================================================================
SIDEBAR
===================================================================== -->
<aside class="sidebar themed-scrollbar" id="sidebar" role="navigation" aria-label="Menú principal">
<!-- Brand -->
<div class="sidebar__brand">
<div class="brand-logo" aria-hidden="true">N</div>
<div class="brand-name">
<span class="brand-name__primary">Nexus</span>
<span class="brand-name__sub">Autoparts POS</span>
</div>
</div>
<!-- Nav -->
<nav class="sidebar__nav">
<div class="nav-section-label">Principal</div>
<a class="nav-item" href="#" role="menuitem">
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>
Dashboard
</a>
<a class="nav-item" href="#" role="menuitem">
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"/><path d="M3 6h18"/><path d="M16 10a4 4 0 01-8 0"/></svg>
Punto de Venta
</a>
<a class="nav-item" href="#" role="menuitem">
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><path d="M21 16V8a2 2 0 00-1-1.73l-7-4a2 2 0 00-2 0l-7 4A2 2 0 003 8v8a2 2 0 001 1.73l7 4a2 2 0 002 0l7-4A2 2 0 0021 16z"/></svg>
Inventario
<span class="nav-item__badge">12</span>
</a>
<a class="nav-item is-active" href="#" role="menuitem" aria-current="page">
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M8 7h8M8 12h8M8 17h5"/></svg>
Catálogo
</a>
<div class="nav-section-label" style="margin-top: var(--space-2);">Gestión</div>
<a class="nav-item" href="#" role="menuitem">
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
Clientes
</a>
<a class="nav-item" href="#" role="menuitem">
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14,2 14,8 20,8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10,9 9,9 8,9"/></svg>
Facturación
</a>
<a class="nav-item" href="#" role="menuitem">
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg>
Contabilidad
</a>
<a class="nav-item" href="#" role="menuitem">
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><polyline points="22,12 18,12 15,21 9,3 6,12 2,12"/></svg>
Reportes
</a>
<div class="nav-section-label" style="margin-top: var(--space-2);">Sistema</div>
<a class="nav-item" href="#" role="menuitem">
<svg class="nav-item__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M19.07 4.93l-1.41 1.41M6.34 17.66l-1.41 1.41M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M12 2v2M12 20v2M2 12h2M20 12h2"/></svg>
Configuración
</a>
</nav>
<!-- User profile -->
<div class="sidebar__profile">
<div class="profile-avatar" aria-hidden="true">JR</div>
<div class="profile-info">
<div class="profile-info__name">José Ramírez</div>
<div class="profile-info__role">Administrador</div>
</div>
<button class="profile-btn" aria-label="Opciones de usuario" title="Opciones de usuario">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/></svg>
</button>
</div>
</aside>
<!-- =====================================================================
MAIN CONTENT
===================================================================== -->
<main class="main-content" id="mainContent">
<!-- Header bar -->
<header class="content-header">
<div style="display:flex;align-items:center;gap:var(--space-3);">
<button class="sidebar-toggle" id="sidebarToggle" aria-label="Abrir menú" aria-expanded="false" aria-controls="sidebar">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
</button>
<nav class="breadcrumb" aria-label="Breadcrumb">
<a class="breadcrumb__link" href="#">Inicio</a>
<span class="breadcrumb__sep" aria-hidden="true"></span>
<span class="breadcrumb__current" aria-current="page">Catálogo</span>
</nav>
</div>
<div class="header-actions">
<button class="icon-btn" aria-label="Notificaciones">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>
<span class="notif-dot" aria-label="3 notificaciones pendientes"></span>
</button>
<button class="icon-btn" aria-label="Ayuda">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
</button>
</div>
</header>
<!-- ===================================================================
PAGE BODY
=================================================================== -->
<div class="page-body themed-scrollbar" id="pageBody">
<!-- Search panel -->
<section class="search-panel" aria-label="Búsqueda por vehículo">
<div class="search-panel__title">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
Buscar por Vehículo
</div>
<!-- Vehicle dropdowns -->
<div class="vehicle-search-row">
<div class="form-group">
<label class="form-label" for="sel-make">Marca / Make</label>
<select class="form-select" id="sel-make" aria-label="Seleccionar marca">
<option value="">— Seleccionar marca —</option>
<option value="toyota" selected>Toyota</option>
<option value="honda">Honda</option>
<option value="nissan">Nissan</option>
<option value="chevrolet">Chevrolet</option>
<option value="ford">Ford</option>
<option value="volkswagen">Volkswagen</option>
<option value="mazda">Mazda</option>
<option value="hyundai">Hyundai</option>
<option value="kia">Kia</option>
<option value="bmw">BMW</option>
<option value="mercedes">Mercedes-Benz</option>
</select>
</div>
<div class="form-group">
<label class="form-label" for="sel-model">Modelo / Model</label>
<select class="form-select" id="sel-model" aria-label="Seleccionar modelo">
<option value="">— Seleccionar modelo —</option>
<option value="corolla" selected>Corolla</option>
<option value="camry">Camry</option>
<option value="hilux">Hilux</option>
<option value="rav4">RAV4</option>
<option value="yaris">Yaris</option>
<option value="prius">Prius</option>
<option value="4runner">4Runner</option>
<option value="tacoma">Tacoma</option>
</select>
</div>
<div class="form-group">
<label class="form-label" for="sel-year">Año / Year</label>
<select class="form-select" id="sel-year" aria-label="Seleccionar año">
<option value="">— Año —</option>
<option value="2024">2024</option>
<option value="2023">2023</option>
<option value="2022">2022</option>
<option value="2021">2021</option>
<option value="2020">2020</option>
<option value="2019">2019</option>
<option value="2018" selected>2018</option>
<option value="2017">2017</option>
<option value="2016">2016</option>
<option value="2015">2015</option>
</select>
</div>
<div class="form-group">
<label class="form-label" style="opacity:0" aria-hidden="true">Buscar</label>
<button class="btn btn-primary" id="vehicleSearchBtn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
Buscar
</button>
</div>
</div>
<!-- Part search -->
<div class="part-search-row">
<div class="form-group">
<label class="form-label" for="inp-part">Número OEM o nombre de pieza</label>
<div class="form-input-with-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
<input
class="form-input"
id="inp-part"
type="text"
placeholder="Ej: 04465-02260, pastillas de freno, sensor de oxígeno..."
aria-label="Buscar por número OEM o nombre de pieza"
/>
</div>
</div>
<div class="form-group">
<label class="form-label" style="opacity:0" aria-hidden="true">Buscar parte</label>
<button class="btn btn-secondary" id="partSearchBtn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
Búsqueda Avanzada
</button>
</div>
</div>
</section>
<!-- Results bar -->
<div class="results-bar">
<div class="results-count">
<strong>1,247</strong> partes encontradas
<span style="font-size:var(--text-body-sm);font-weight:var(--font-weight-regular);color:var(--color-text-muted);margin-left:var(--space-2);">para Toyota Corolla 2018</span>
</div>
<div class="filters-row">
<span class="filters-label">Filtrar:</span>
<button class="chip is-active" data-chip="frenos" aria-pressed="true">Frenos</button>
<button class="chip" data-chip="motor" aria-pressed="false">Motor</button>
<button class="chip" data-chip="suspension" aria-pressed="false">Suspensión</button>
<button class="chip" data-chip="electrico" aria-pressed="false">Eléctrico</button>
<button class="chip" data-chip="transmision" aria-pressed="false">Transmisión</button>
<button class="chip" data-chip="escape" aria-pressed="false">Escape</button>
<button class="chip" data-chip="carroceria" aria-pressed="false">Carrocería</button>
<button class="chip" data-chip="enfriamiento" aria-pressed="false">Enfriamiento</button>
</div>
</div>
<!-- Catalog toolbar -->
<div class="catalog-toolbar">
<div class="sort-row">
<span class="sort-label">Ordenar por:</span>
<select class="sort-select" aria-label="Ordenar resultados">
<option>Relevancia</option>
<option>Precio: Menor a Mayor</option>
<option>Precio: Mayor a Menor</option>
<option>Nombre AZ</option>
<option>Marca</option>
<option>Disponibilidad</option>
</select>
</div>
<div role="group" aria-label="Cambiar vista" class="view-toggle">
<button class="view-btn is-active" id="btnViewGrid" title="Vista en cuadrícula" aria-pressed="true">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>
</button>
<button class="view-btn" id="btnViewList" title="Vista en lista" aria-pressed="false">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
</button>
</div>
</div>
<!-- Product grid -->
<div class="product-grid" id="productGrid" role="list" aria-label="Resultados del catálogo">
<!-- Card 1: Pastillas de Freno -->
<article class="product-card" role="listitem">
<div class="product-card__image">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5"/><circle cx="12" cy="12" r="1.5" fill="currentColor"/><path d="M12 3v2M12 19v2M3 12h2M19 12h2"/></svg>
<span class="product-card__image-label" aria-hidden="true">IMG</span>
<div class="stock-badge stock-ok" role="status" aria-label="En stock">En stock</div>
</div>
<div class="product-card__body">
<div class="product-card__category">Frenos</div>
<div class="product-card__name">Pastillas de Freno Delanteras Cerámicas</div>
<div class="product-card__oem" title="Número OEM">OEM: 04465-02260</div>
<div class="product-card__brand">
<span>Akebono</span>
<div class="product-card__brand-dot" aria-hidden="true"></div>
<span style="color:var(--color-text-muted);">Japón</span>
</div>
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 20182022">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
Compatible con: Toyota Corolla 20182022
</div>
</div>
<div class="product-card__footer">
<div class="product-card__pricing">
<div class="product-card__price">$485.00</div>
<div class="product-card__price-unit">MXN / juego</div>
</div>
<button class="btn-add" aria-label="Agregar Pastillas de Freno Delanteras al carrito">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
Agregar
</button>
</div>
</article>
<!-- Card 2: Amortiguador -->
<article class="product-card" role="listitem">
<div class="product-card__image">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><line x1="12" y1="2" x2="12" y2="22"/><path d="M8 6h8M8 10h8M6 14h12M7 18h10"/></svg>
<span class="product-card__image-label" aria-hidden="true">IMG</span>
<div class="stock-badge stock-ok" role="status" aria-label="En stock">En stock</div>
</div>
<div class="product-card__body">
<div class="product-card__category">Suspensión</div>
<div class="product-card__name">Amortiguador Delantero Gas KYB Excel-G</div>
<div class="product-card__oem" title="Número OEM">OEM: 339175</div>
<div class="product-card__brand">
<span>KYB</span>
<div class="product-card__brand-dot" aria-hidden="true"></div>
<span style="color:var(--color-text-muted);">Japón</span>
</div>
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 20142019">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
Compatible con: Toyota Corolla 20142019
</div>
</div>
<div class="product-card__footer">
<div class="product-card__pricing">
<div class="product-card__price">$1,250.00</div>
<div class="product-card__price-unit">MXN / pieza</div>
</div>
<button class="btn-add" aria-label="Agregar Amortiguador KYB al carrito">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
Agregar
</button>
</div>
</article>
<!-- Card 3: Sensor de Oxígeno -->
<article class="product-card" role="listitem">
<div class="product-card__image">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><path d="M12 22V12M12 12C12 8 8 6 8 6s4-2 4 2M12 12c0-4 4-6 4-6s-4-2-4 2"/><circle cx="12" cy="5" r="2"/></svg>
<span class="product-card__image-label" aria-hidden="true">IMG</span>
<div class="stock-badge stock-low" role="status" aria-label="Stock bajo">Últimas 3</div>
</div>
<div class="product-card__body">
<div class="product-card__category">Eléctrico</div>
<div class="product-card__name">Sensor de Oxígeno Aguas Arriba Denso</div>
<div class="product-card__oem" title="Número OEM">OEM: 234-4209</div>
<div class="product-card__brand">
<span>Denso</span>
<div class="product-card__brand-dot" aria-hidden="true"></div>
<span style="color:var(--color-text-muted);">Japón</span>
</div>
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 20092019">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
Compatible con: Toyota Corolla 20092019
</div>
</div>
<div class="product-card__footer">
<div class="product-card__pricing">
<div class="product-card__price">$890.00</div>
<div class="product-card__price-unit">MXN / pieza</div>
</div>
<button class="btn-add" aria-label="Agregar Sensor de Oxígeno Denso al carrito">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
Agregar
</button>
</div>
</article>
<!-- Card 4: Filtro de Aceite -->
<article class="product-card" role="listitem">
<div class="product-card__image">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><path d="M4 4h16v4L12 20 4 8z"/><path d="M4 8h16"/></svg>
<span class="product-card__image-label" aria-hidden="true">IMG</span>
<div class="stock-badge stock-ok" role="status" aria-label="En stock">En stock</div>
</div>
<div class="product-card__body">
<div class="product-card__category">Motor</div>
<div class="product-card__name">Filtro de Aceite Motor Toyota Original</div>
<div class="product-card__oem" title="Número OEM">OEM: 90915-YZZE1</div>
<div class="product-card__brand">
<span>Toyota Genuine</span>
<div class="product-card__brand-dot" aria-hidden="true"></div>
<span style="color:var(--color-text-muted);">OEM</span>
</div>
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 20142024">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
Compatible con: Toyota Corolla 20142024
</div>
</div>
<div class="product-card__footer">
<div class="product-card__pricing">
<div class="product-card__price">$145.00</div>
<div class="product-card__price-unit">MXN / pieza</div>
</div>
<button class="btn-add" aria-label="Agregar Filtro de Aceite Toyota al carrito">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
Agregar
</button>
</div>
</article>
<!-- Card 5: Banda de Distribución Kit -->
<article class="product-card" role="listitem">
<div class="product-card__image">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><circle cx="7" cy="17" r="3"/><circle cx="17" cy="7" r="3"/><path d="M7 14V10a2 2 0 012-2h6"/><path d="M17 10v4a2 2 0 01-2 2H9"/></svg>
<span class="product-card__image-label" aria-hidden="true">IMG</span>
<div class="stock-badge stock-ok" role="status" aria-label="En stock">En stock</div>
</div>
<div class="product-card__body">
<div class="product-card__category">Motor</div>
<div class="product-card__name">Kit Banda de Distribución con Bomba de Agua Gates</div>
<div class="product-card__oem" title="Número OEM">OEM: TCK328B</div>
<div class="product-card__brand">
<span>Gates</span>
<div class="product-card__brand-dot" aria-hidden="true"></div>
<span style="color:var(--color-text-muted);">EUA</span>
</div>
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 20092020">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
Compatible con: Toyota Corolla 20092020
</div>
</div>
<div class="product-card__footer">
<div class="product-card__pricing">
<div class="product-card__price">$2,380.00</div>
<div class="product-card__price-unit">MXN / kit</div>
</div>
<button class="btn-add" aria-label="Agregar Kit Banda de Distribución Gates al carrito">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
Agregar
</button>
</div>
</article>
<!-- Card 6: Disco de Freno -->
<article class="product-card" role="listitem">
<div class="product-card__image">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="4"/><path d="M12 3v3M12 18v3M3 12h3M18 12h3"/></svg>
<span class="product-card__image-label" aria-hidden="true">IMG</span>
<div class="stock-badge stock-out" role="status" aria-label="Sin stock">Agotado</div>
</div>
<div class="product-card__body">
<div class="product-card__category">Frenos</div>
<div class="product-card__name">Disco de Freno Ventilado Delantero Brembo</div>
<div class="product-card__oem" title="Número OEM">OEM: 09.9807.11</div>
<div class="product-card__brand">
<span>Brembo</span>
<div class="product-card__brand-dot" aria-hidden="true"></div>
<span style="color:var(--color-text-muted);">Italia</span>
</div>
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 20142022">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
Compatible con: Toyota Corolla 20142022
</div>
</div>
<div class="product-card__footer">
<div class="product-card__pricing">
<div class="product-card__price">$1,940.00</div>
<div class="product-card__price-unit">MXN / pieza</div>
</div>
<button class="btn-add" aria-label="Producto agotado" disabled style="opacity:0.45;cursor:not-allowed;">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M4.93 4.93l14.14 14.14"/></svg>
Agotado
</button>
</div>
</article>
</div>
<!-- /product-grid -->
<!-- Pagination -->
<nav class="pagination" aria-label="Paginación de resultados">
<button class="page-item page-item--wide is-disabled" aria-label="Página anterior" disabled>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="15,18 9,12 15,6"/></svg>
Anterior
</button>
<button class="page-item is-active" aria-label="Página 1, actual" aria-current="page">1</button>
<button class="page-item" aria-label="Ir a página 2">2</button>
<button class="page-item" aria-label="Ir a página 3">3</button>
<span class="page-ellipsis" aria-hidden="true"></span>
<button class="page-item" aria-label="Ir a página 41">41</button>
<button class="page-item" aria-label="Ir a página 42">42</button>
<button class="page-item page-item--wide" aria-label="Ir a página siguiente">
Siguiente
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="9,18 15,12 9,6"/></svg>
</button>
</nav>
</div>
<!-- /page-body -->
</main>
<!-- /main-content -->
</div>
<!-- /app-shell -->
<!-- =========================================================================
JAVASCRIPT
========================================================================= -->
<script>
'use strict';
/* =========================================================================
THEME SWITCHING
========================================================================= */
const html = document.documentElement;
const themeButtons = document.querySelectorAll('[data-theme-switch]');
function applyTheme(theme) {
html.setAttribute('data-theme', theme);
themeButtons.forEach(btn => {
const isActive = btn.dataset.themeSwitch === theme;
btn.classList.toggle('is-active', isActive);
btn.setAttribute('aria-pressed', String(isActive));
});
try {
localStorage.setItem('nexus-theme', theme);
} catch (_) { /* ignore */ }
}
themeButtons.forEach(btn => {
btn.addEventListener('click', () => applyTheme(btn.dataset.themeSwitch));
});
// Restore saved theme
(function () {
let saved;
try { saved = localStorage.getItem('nexus-theme'); } catch (_) { }
if (saved === 'industrial' || saved === 'modern') applyTheme(saved);
})();
/* =========================================================================
FILTER CHIP TOGGLING
========================================================================= */
const chips = document.querySelectorAll('[data-chip]');
chips.forEach(chip => {
chip.addEventListener('click', () => {
const isActive = chip.classList.toggle('is-active');
chip.setAttribute('aria-pressed', String(isActive));
});
});
/* =========================================================================
VIEW TOGGLE (Grid / List)
========================================================================= */
const productGrid = document.getElementById('productGrid');
const btnViewGrid = document.getElementById('btnViewGrid');
const btnViewList = document.getElementById('btnViewList');
function setView(view) {
const isGrid = view === 'grid';
productGrid.classList.toggle('view-list', !isGrid);
btnViewGrid.classList.toggle('is-active', isGrid);
btnViewList.classList.toggle('is-active', !isGrid);
btnViewGrid.setAttribute('aria-pressed', String(isGrid));
btnViewList.setAttribute('aria-pressed', String(!isGrid));
try {
localStorage.setItem('nexus-catalog-view', view);
} catch (_) { /* ignore */ }
}
btnViewGrid.addEventListener('click', () => setView('grid'));
btnViewList.addEventListener('click', () => setView('list'));
// Restore saved view
(function () {
let saved;
try { saved = localStorage.getItem('nexus-catalog-view'); } catch (_) { }
if (saved === 'list') setView('list');
})();
/* =========================================================================
MOBILE SIDEBAR TOGGLE
========================================================================= */
const sidebar = document.getElementById('sidebar');
const sidebarOverlay = document.getElementById('sidebarOverlay');
const sidebarToggle = document.getElementById('sidebarToggle');
function openSidebar() {
sidebar.classList.add('is-open');
sidebarOverlay.classList.add('is-open');
sidebarToggle.setAttribute('aria-expanded', 'true');
document.body.style.overflow = 'hidden';
}
function closeSidebar() {
sidebar.classList.remove('is-open');
sidebarOverlay.classList.remove('is-open');
sidebarToggle.setAttribute('aria-expanded', 'false');
document.body.style.overflow = '';
}
sidebarToggle.addEventListener('click', () => {
if (sidebar.classList.contains('is-open')) closeSidebar();
else openSidebar();
});
sidebarOverlay.addEventListener('click', closeSidebar);
// Close sidebar on Escape
document.addEventListener('keydown', e => {
if (e.key === 'Escape' && sidebar.classList.contains('is-open')) closeSidebar();
});
// Close sidebar if viewport grows beyond mobile breakpoint
const mq = window.matchMedia('(min-width: 769px)');
mq.addEventListener('change', e => {
if (e.matches) closeSidebar();
});
/* =========================================================================
PAGINATION INTERACTION
========================================================================= */
const pageItems = document.querySelectorAll('.page-item:not(.is-disabled):not([disabled])');
pageItems.forEach(item => {
if (item.id === 'paginationPrev' || item.id === 'paginationNext') return;
item.addEventListener('click', function () {
// Remove active from all numbered items (not prev/next)
document.querySelectorAll('.page-item:not(.page-item--wide)').forEach(p => {
p.classList.remove('is-active');
p.removeAttribute('aria-current');
});
this.classList.add('is-active');
this.setAttribute('aria-current', 'page');
// Scroll back to top of results
document.getElementById('pageBody').scrollTo({ top: 0, behavior: 'smooth' });
});
});
/* =========================================================================
SEARCH BUTTON FEEDBACK
========================================================================= */
document.getElementById('vehicleSearchBtn').addEventListener('click', function () {
const label = this.querySelector('svg') ? this : this;
const originalText = this.textContent.trim();
this.disabled = true;
this.style.opacity = '0.7';
setTimeout(() => {
this.disabled = false;
this.style.opacity = '';
}, 800);
});
</script>
</body>
</html>