Reemplazados todos los href="#" en nav-items y nav-links con las rutas reales (/pos/dashboard, /pos/sale, /pos/catalog, etc.) en catalog, inventory, customers, dashboard, config, reports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2145 lines
68 KiB
HTML
2145 lines
68 KiB
HTML
<!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;
|
||
}
|
||
|
||
/* =========================================================================
|
||
EMPTY STATE COMPONENT
|
||
========================================================================= */
|
||
|
||
.empty-state {
|
||
display: none;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
text-align: center;
|
||
max-width: 320px;
|
||
padding: var(--space-8) var(--space-4);
|
||
margin: var(--space-10) auto;
|
||
width: 100%;
|
||
}
|
||
|
||
.empty-state.is-visible {
|
||
display: flex;
|
||
}
|
||
|
||
.empty-state__icon {
|
||
font-size: 48px;
|
||
line-height: 1;
|
||
margin-bottom: var(--space-4);
|
||
opacity: 0.6;
|
||
filter: grayscale(30%);
|
||
}
|
||
|
||
.empty-state__title {
|
||
font-family: var(--font-heading);
|
||
font-size: var(--text-h5);
|
||
font-weight: var(--heading-weight-secondary);
|
||
color: var(--color-text-primary);
|
||
margin-bottom: var(--space-2);
|
||
}
|
||
|
||
.empty-state__subtitle {
|
||
font-size: var(--text-body-sm);
|
||
color: var(--color-text-muted);
|
||
line-height: 1.5;
|
||
margin-bottom: var(--space-5);
|
||
}
|
||
|
||
.empty-state__action {
|
||
padding: var(--space-2) var(--space-5);
|
||
font-family: var(--font-body);
|
||
font-size: var(--text-body-sm);
|
||
font-weight: 500;
|
||
border-radius: var(--radius-md);
|
||
cursor: pointer;
|
||
transition: var(--transition-fast);
|
||
border: 1px solid var(--btn-secondary-border);
|
||
background: var(--btn-secondary-bg);
|
||
color: var(--btn-secondary-text);
|
||
}
|
||
|
||
.empty-state__action:hover {
|
||
background: var(--btn-secondary-bg-hover);
|
||
box-shadow: var(--shadow-sm);
|
||
}
|
||
|
||
/* =========================================================================
|
||
OFFLINE BANNER
|
||
========================================================================= */
|
||
|
||
@keyframes slideDown { from { transform: translateY(-100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
|
||
@keyframes slideUp { from { transform: translateY(0); opacity: 1; } to { transform: translateY(-100%); opacity: 0; } }
|
||
|
||
.banner {
|
||
display: flex; align-items: center; gap: var(--space-3);
|
||
padding: var(--space-3) var(--space-4); border-radius: var(--radius-md);
|
||
font-size: var(--text-body-sm); font-weight: 500; line-height: 1.4;
|
||
}
|
||
.banner--warning {
|
||
background: var(--color-warning-light, #fef9c3); color: var(--color-warning-dark, #854d0e);
|
||
border: 1px solid var(--color-warning, #eab308);
|
||
}
|
||
.banner--success {
|
||
background: var(--color-success-light, #dcfce7); color: var(--color-success-dark, #166534);
|
||
border: 1px solid var(--color-success, #22c55e);
|
||
}
|
||
.banner--error {
|
||
background: var(--color-error-light, #fef2f2); color: var(--color-error-dark, #991b1b);
|
||
border: 1px solid var(--color-error, #ef4444);
|
||
}
|
||
.banner--dismissing { animation: slideUp 0.3s ease-in forwards; }
|
||
.banner__icon { font-size: 18px; flex-shrink: 0; }
|
||
.banner__text { flex: 1; }
|
||
.banner__text strong { font-weight: 700; }
|
||
.banner__dismiss {
|
||
background: none; border: none; cursor: pointer; font-size: 18px;
|
||
padding: var(--space-1); opacity: 0.7; color: inherit;
|
||
}
|
||
.banner__dismiss:hover { opacity: 1; }
|
||
|
||
/* =========================================================================
|
||
CART SIDEBAR
|
||
========================================================================= */
|
||
|
||
.cart-fab {
|
||
position: fixed;
|
||
bottom: var(--space-6);
|
||
right: var(--space-6);
|
||
z-index: var(--z-modal);
|
||
width: 56px;
|
||
height: 56px;
|
||
border-radius: var(--radius-full);
|
||
background: var(--color-primary);
|
||
color: var(--color-text-inverse);
|
||
border: none;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: var(--shadow-lg);
|
||
transition: var(--transition-fast);
|
||
}
|
||
|
||
.cart-fab:hover {
|
||
transform: scale(1.08);
|
||
box-shadow: var(--shadow-xl);
|
||
}
|
||
|
||
.cart-fab__badge {
|
||
position: absolute;
|
||
top: -4px;
|
||
right: -4px;
|
||
min-width: 20px;
|
||
height: 20px;
|
||
padding: 0 5px;
|
||
border-radius: var(--radius-full);
|
||
background: var(--color-error, #ef4444);
|
||
color: #fff;
|
||
font-size: 11px;
|
||
font-weight: var(--font-weight-bold);
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
line-height: 1;
|
||
}
|
||
|
||
.cart-sidebar {
|
||
position: fixed;
|
||
top: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
width: 360px;
|
||
max-width: 100vw;
|
||
z-index: var(--z-modal);
|
||
background: var(--color-bg-elevated);
|
||
border-left: 1px solid var(--color-border);
|
||
box-shadow: var(--shadow-xl);
|
||
display: flex;
|
||
flex-direction: column;
|
||
transform: translateX(100%);
|
||
transition: transform var(--duration-normal) var(--ease-in-out);
|
||
}
|
||
|
||
.cart-sidebar.open {
|
||
transform: translateX(0);
|
||
}
|
||
|
||
.cart-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: var(--space-4) var(--space-5);
|
||
border-bottom: 1px solid var(--color-border);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.cart-header h3 {
|
||
font-family: var(--font-heading);
|
||
font-size: var(--text-h5);
|
||
font-weight: var(--heading-weight-secondary);
|
||
color: var(--color-text-primary);
|
||
}
|
||
|
||
.cart-items {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
padding: var(--space-3) var(--space-4);
|
||
}
|
||
|
||
.cart-item {
|
||
display: flex;
|
||
gap: var(--space-3);
|
||
padding: var(--space-3) 0;
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.cart-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.cart-footer {
|
||
padding: var(--space-4) var(--space-5);
|
||
border-top: 1px solid var(--color-border);
|
||
flex-shrink: 0;
|
||
background: var(--color-bg-elevated);
|
||
}
|
||
|
||
.cart-totals {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-1);
|
||
font-size: var(--text-body-sm);
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
.cart-overlay {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: calc(var(--z-modal) - 1);
|
||
background: rgba(0, 0, 0, 0.3);
|
||
backdrop-filter: blur(2px);
|
||
display: none;
|
||
}
|
||
|
||
.cart-overlay.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="/pos/dashboard" 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="/pos/sale" 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="/pos/inventory" 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="/pos/catalog" 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="/pos/customers" 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="/pos/invoicing" 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="/pos/accounting" 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="/pos/reports" 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="/pos/config" 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 A–Z</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 — populated dynamically by catalog.js -->
|
||
<div class="product-grid" id="productGrid" role="list" aria-label="Resultados del catálogo">
|
||
<!-- Cards loaded from API -->
|
||
|
||
</div>
|
||
<!-- /product-grid -->
|
||
|
||
<!-- Empty State (shown when no results) -->
|
||
<div class="empty-state" id="emptyState">
|
||
<div class="empty-state__icon">🔎</div>
|
||
<div class="empty-state__title" id="emptyStateTitle">No se encontraron productos</div>
|
||
<div class="empty-state__subtitle" id="emptyStateSubtitle">Intenta con otro termino de busqueda o verifica el numero de parte</div>
|
||
<button class="empty-state__action" onclick="document.querySelector('.search-box input').value=''; document.querySelector('.search-box input').focus();">Limpiar filtros</button>
|
||
</div>
|
||
|
||
<!-- 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>
|
||
|
||
<!-- Cart FAB (floating action button) -->
|
||
<button class="cart-fab" id="cartFab" onclick="CatalogApp.toggleCart()" aria-label="Abrir carrito">
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6"/></svg>
|
||
<span class="cart-fab__badge" id="cartBadge">0</span>
|
||
</button>
|
||
|
||
<!-- Cart overlay -->
|
||
<div class="cart-overlay" id="cartOverlay" onclick="CatalogApp.toggleCart()"></div>
|
||
|
||
<!-- Cart sidebar -->
|
||
<aside class="cart-sidebar" id="cartSidebar">
|
||
<div class="cart-header">
|
||
<h3>Carrito</h3>
|
||
<button onclick="CatalogApp.toggleCart()" class="btn btn-ghost" aria-label="Cerrar carrito" style="background:none;border:none;cursor:pointer;font-size:1.4rem;color:var(--color-text-secondary);padding:var(--space-1);">✕</button>
|
||
</div>
|
||
<div class="cart-items" id="cartItems"></div>
|
||
<div class="cart-empty" id="cartEmpty" style="display:none;padding:2rem;text-align:center;color:var(--color-text-muted);">Carrito vacio</div>
|
||
<div class="cart-footer">
|
||
<div class="cart-totals">
|
||
<div>Subtotal: <span id="cartSubtotal">$0.00</span></div>
|
||
<div>IVA 16%: <span id="cartTax">$0.00</span></div>
|
||
<div style="font-weight:bold;font-size:1.2em;">Total: <span id="cartTotal">$0.00</span></div>
|
||
</div>
|
||
<button id="checkoutBtn" class="btn btn-primary" style="width:100%;margin-top:var(--space-3);padding:var(--space-3);font-size:var(--text-body);font-weight:var(--font-weight-semibold);cursor:pointer;" onclick="CatalogApp.goToCheckout()">Ir a cobrar →</button>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- Offline Banner -->
|
||
<div id="offlineBanner" class="banner banner--warning" style="display:none;position:fixed;top:0;left:0;right:0;z-index:9999;border-radius:0;animation:none;">
|
||
<span class="banner__icon"></span>
|
||
<span class="banner__text" id="offlineBannerText"><strong>Modo offline</strong> — Funciones limitadas. Solo consultas en cache disponibles.</span>
|
||
<button class="banner__dismiss" onclick="document.getElementById('offlineBanner').style.display='none'" aria-label="Cerrar">×</button>
|
||
</div>
|
||
|
||
<script src="/pos/static/js/app-init.js"></script>
|
||
<script src="/pos/static/js/catalog.js"></script>
|
||
<script src="/pos/static/js/offline-banner.js"></script>
|
||
</body>
|
||
</html>
|