Files
Autoparts-DB/pos/static/css/pos-glass.min.css
consultoria-as 21959f1b37 FASE 7d: Lazy Loading + Minificación + Auto-serve minified
Cambios implementados:

1. Lazy loading de imágenes:
   - catalog.js: loading="lazy" decoding="async" en part cards y detail panel
   - inventory.js: lazy loading en imagen de detalle de item

2. Minificación de assets:
   - scripts/minify-assets.sh: minifica JS (terser) y CSS para POS y Dashboard
   - 25 archivos .min.js + 5 .min.css generados en pos/static/
   - 14 archivos .min.js + 8 .min.css generados en dashboard/

3. Nginx auto-serve minified:
   - try_files $1.min.js antes de servir .js original
   - try_files $1.min.css antes de servir .css original
   - Transparente para los templates HTML (cero cambios en HTML)

4. Cache warming script:
   - scripts/warm_vehicle_cache.py: pobla Redis con vehicle info por batches
   - Mitiga DISTINCT ON + 4 JOINs sobre 2B filas
   - Corre en background, procesa ~1.5M parts

Tests: 73/73 pasando
2026-04-27 08:34:24 +00:00

684 lines
17 KiB
CSS
Raw Permalink 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.
/* ==========================================================================
POS-GLASS.CSS — Pixel-Perfect glassmorphism overlay for Nexus POS
Load AFTER tokens.css. Applies glass effects, glow, 3D buttons,
and animations to all POS pages without modifying inline styles.
========================================================================== */
/* ── Hidden scrollbar (global) ── */
html { scrollbar-width: none; }
html::-webkit-scrollbar { width: 0; }
/* ── Smooth font rendering ── */
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* ==========================================================================
SIDEBAR — Glass treatment
========================================================================== */
.sidebar,
.pos-sidebar {
background: var(--glass-bg-strong) !important;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border-right: 1px solid var(--glass-border) !important;
}
.sidebar__logo {
position: relative;
}
.sidebar__logo-text {
position: relative;
}
/* Glow under logo text */
.sidebar__logo-text::after {
content: '';
position: absolute;
bottom: -4px;
left: 0;
right: 0;
height: 2px;
background: var(--gradient-accent);
border-radius: 1px;
opacity: 0.4;
filter: blur(2px);
}
/* Nav items — hover glow */
.sidebar__nav a,
.sidebar__nav-item,
.sidebar .nav-item {
transition: all 0.25s var(--ease-out) !important;
border-radius: var(--radius-md);
}
.sidebar__nav a:hover,
.sidebar__nav-item:hover,
.sidebar .nav-item:hover {
box-shadow: 0 0 12px var(--glow-color-soft);
}
.sidebar__nav a.active,
.sidebar__nav-item.active,
.sidebar .nav-item.active {
box-shadow: 0 0 16px var(--glow-color-soft), inset 0 0 0 1px var(--glass-border);
}
/* ==========================================================================
THEME BAR — Glass
========================================================================== */
.theme-bar {
background: var(--glass-bg-strong) !important;
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border-bottom: 1px solid var(--glass-border) !important;
}
/* ==========================================================================
CARDS — Glass with glow hover
========================================================================== */
.kpi-card,
.table-card,
.card,
.stat-card,
.chart-card,
.alert-card,
.config-card,
.fleet-card,
.report-card,
.invoice-card,
.customer-card,
.panel {
background: var(--glass-bg) !important;
backdrop-filter: blur(var(--glass-blur));
-webkit-backdrop-filter: blur(var(--glass-blur));
border: 1px solid var(--glass-border) !important;
transition: all 0.3s var(--ease-out) !important;
position: relative;
overflow: hidden;
}
/* Accent top-line on hover */
.kpi-card::before,
.table-card::before,
.chart-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: var(--gradient-accent);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.4s var(--ease-out);
z-index: 1;
}
.kpi-card:hover::before,
.table-card:hover::before,
.chart-card:hover::before {
transform: scaleX(1);
}
.kpi-card:hover,
.table-card:hover,
.card:hover,
.stat-card:hover,
.chart-card:hover,
.config-card:hover,
.fleet-card:hover,
.report-card:hover {
border-color: var(--color-border-accent) !important;
box-shadow: 0 4px 20px var(--glow-color-soft);
}
/* KPI card accent bar — add glow */
.kpi-card__accent-bar {
box-shadow: 0 0 8px var(--glow-color-soft);
}
/* ==========================================================================
BUTTONS — 3D depth effect
========================================================================== */
/* Primary buttons */
.btn--primary,
button.primary,
.btn-primary,
input[type="submit"],
button[type="submit"] {
background: var(--gradient-accent) !important;
border: none !important;
box-shadow: 0 3px 0 var(--color-primary-active),
0 4px 10px var(--glow-color-soft) !important;
transition: all 0.25s var(--ease-out) !important;
position: relative;
overflow: hidden;
}
.btn--primary:hover,
button.primary:hover,
.btn-primary:hover,
input[type="submit"]:hover,
button[type="submit"]:hover {
transform: translateY(-1px);
box-shadow: 0 4px 0 var(--color-primary-active),
0 8px 20px var(--glow-color) !important;
}
.btn--primary:active,
button.primary:active,
.btn-primary:active,
input[type="submit"]:active,
button[type="submit"]:active {
transform: translateY(1px);
box-shadow: 0 1px 0 var(--color-primary-active) !important;
}
/* Ghost / secondary buttons — glass */
.btn--ghost,
.btn--secondary,
.btn-secondary,
.btn-ghost,
button.secondary {
background: var(--glass-bg) !important;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid var(--glass-border) !important;
transition: all 0.25s var(--ease-out) !important;
}
.btn--ghost:hover,
.btn--secondary:hover,
.btn-secondary:hover,
.btn-ghost:hover,
button.secondary:hover {
border-color: var(--color-border-accent) !important;
box-shadow: 0 0 16px var(--glow-color-soft);
}
/* ==========================================================================
INPUTS — Glass with focus glow
========================================================================== */
input[type="text"],
input[type="number"],
input[type="email"],
input[type="password"],
input[type="search"],
input[type="tel"],
input[type="date"],
input[type="url"],
textarea,
select,
.search-input,
.filter-input {
background: var(--glass-bg) !important;
border: 1px solid var(--glass-border) !important;
transition: all 0.25s var(--ease-out) !important;
}
input[type="text"]:focus,
input[type="number"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
input[type="search"]:focus,
input[type="tel"]:focus,
input[type="date"]:focus,
input[type="url"]:focus,
textarea:focus,
select:focus,
.search-input:focus,
.filter-input:focus {
border-color: var(--color-border-focus) !important;
box-shadow: 0 0 0 3px var(--glow-color-soft), 0 0 16px var(--glow-color-soft) !important;
outline: none;
}
/* ==========================================================================
TABLES — Subtle glass rows
========================================================================== */
table thead th {
background: var(--glass-bg) !important;
backdrop-filter: blur(8px);
font-family: var(--font-mono);
font-size: var(--text-caption);
text-transform: uppercase;
letter-spacing: var(--tracking-wider);
}
table tbody tr {
transition: all 0.2s ease !important;
}
table tbody tr:hover {
background: var(--glass-highlight) !important;
box-shadow: inset 0 0 0 1px var(--glass-border);
}
/* ==========================================================================
MODALS — Glass overlay + glass content
========================================================================== */
.modal-overlay,
.overlay,
.modal-backdrop {
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
}
.modal,
.modal-content,
.modal-dialog,
.dialog {
background: var(--glass-bg-strong) !important;
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
border: 1px solid var(--glass-border) !important;
box-shadow: 0 24px 48px rgba(0,0,0,0.3) !important;
}
/* ==========================================================================
TABS — Glass active state
========================================================================== */
.tab,
.tab-btn,
.tabs button {
transition: all 0.25s var(--ease-out) !important;
border-radius: var(--radius-md);
}
.tab.active,
.tab-btn.active,
.tabs button.active {
background: var(--color-primary-muted) !important;
box-shadow: 0 0 12px var(--glow-color-soft);
border-color: var(--color-border-accent) !important;
}
/* ==========================================================================
BADGES / TAGS — Subtle glow
========================================================================== */
.badge,
.tag,
.status-badge,
.pill {
backdrop-filter: blur(4px);
transition: all 0.2s ease;
}
/* ==========================================================================
SCROLL REVEAL — Available for any POS page that wants it
========================================================================== */
.nx-reveal {
opacity: 0;
transform: translateY(24px);
transition: opacity 0.6s var(--ease-out), transform 0.6s var(--ease-out);
}
.nx-reveal.is-visible {
opacity: 1;
transform: translateY(0);
}
.nx-stagger > .nx-reveal:nth-child(1) { transition-delay: 0ms; }
.nx-stagger > .nx-reveal:nth-child(2) { transition-delay: 80ms; }
.nx-stagger > .nx-reveal:nth-child(3) { transition-delay: 160ms; }
.nx-stagger > .nx-reveal:nth-child(4) { transition-delay: 240ms; }
.nx-stagger > .nx-reveal:nth-child(5) { transition-delay: 320ms; }
.nx-stagger > .nx-reveal:nth-child(6) { transition-delay: 400ms; }
/* ==========================================================================
TOAST / NOTIFICATIONS — Glass
========================================================================== */
.toast,
.notification,
.snackbar,
.alert {
background: var(--glass-bg-strong) !important;
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border: 1px solid var(--glass-border) !important;
}
/* ==========================================================================
DROPDOWN / POPOVER — Glass
========================================================================== */
.dropdown-menu,
.popover,
.autocomplete-list,
.suggestion-list {
background: var(--glass-bg-strong) !important;
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border: 1px solid var(--glass-border) !important;
box-shadow: 0 8px 32px rgba(0,0,0,0.2) !important;
}
/* ==========================================================================
STATUS BAR (POS) — Glass
========================================================================== */
.status-bar,
.pos-status-bar {
background: var(--glass-bg-strong) !important;
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border-bottom: 1px solid var(--glass-border) !important;
}
/* ==========================================================================
LOADING SPINNER — Glow animation
========================================================================== */
.spinner,
.loading-spinner {
animation: nx-glow-pulse 1.5s ease-in-out infinite;
}
/* ==========================================================================
ANIMATIONS — Available keyframes
========================================================================== */
@keyframes pos-fade-in {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0); }
}
/* Apply subtle entry animation to main content area */
.content,
.main-content,
main {
animation: pos-fade-in 0.4s var(--ease-out) both;
}
/* ==========================================================================
DASHED BORDER ACCENTS (Pixel-Perfect style)
========================================================================== */
.section-divider,
hr {
border: none;
border-top: 1px dashed var(--glass-border);
margin: var(--space-4) 0;
}
/* ==========================================================================
TABLET RESPONSIVE — Adaptive layout for 768px-1024px screens
Applied globally to all POS pages via pos-glass.css.
Targets iPad (768×1024), Android tablets (800×1280), and similar.
========================================================================== */
/* ── Tablet portrait (768-1023px) — sidebar collapses, grids reflow ── */
@media (max-width: 1023px) {
/* Sidebar collapses to an overlay drawer */
.sidebar,
.pos-sidebar {
position: fixed !important;
top: 0 !important;
left: 0 !important;
bottom: 0 !important;
z-index: var(--z-modal) !important;
transform: translateX(-100%) !important;
transition: transform 0.3s var(--ease-out) !important;
width: 260px !important;
}
.sidebar.open,
.pos-sidebar.open {
transform: translateX(0) !important;
box-shadow: 0 0 40px rgba(0,0,0,0.3) !important;
}
.sidebar-overlay {
display: none !important;
position: fixed !important;
inset: 0 !important;
z-index: calc(var(--z-modal) - 1) !important;
background: rgba(0,0,0,0.5) !important;
}
.sidebar-overlay.open {
display: block !important;
}
/* App shell: full width when sidebar is hidden */
.app-shell {
flex-direction: column !important;
}
.app-shell > main,
.app-shell > .main-content,
.app-shell > .content,
.main-content,
.content {
margin-left: 0 !important;
width: 100% !important;
}
/* Show hamburger button */
.hamburger-btn {
display: flex !important;
}
/* Touch-friendly targets — minimum 44px tap area */
button,
.btn,
.nav-card,
.tab-btn,
.tab,
.part-card,
.search-result-item,
table tbody tr,
.kpi-card {
min-height: 44px;
}
/* Larger text for readability on tablets */
.kpi-card__value {
font-size: 1.5rem !important;
}
/* Grid reflow: 2 columns instead of 3-4 */
.kpi-grid {
grid-template-columns: repeat(2, 1fr) !important;
}
.nav-grid {
grid-template-columns: repeat(2, 1fr) !important;
}
/* Tables: horizontal scroll wrapper on narrow screens */
.table-wrap,
.table-card {
overflow-x: auto !important;
-webkit-overflow-scrolling: touch;
}
/* POS-specific: if the POS has a side panel (cart), stack vertically */
.pos-layout {
flex-direction: column !important;
}
.pos-layout .pos-cart,
.pos-layout .cart-panel {
width: 100% !important;
max-width: 100% !important;
height: auto !important;
max-height: 40vh !important;
}
/* Content headers: tighter padding */
.content-header,
.header,
.page-header {
padding: var(--space-3) var(--space-4) !important;
}
/* Search bar: full width */
.search-bar,
.search-wrapper {
width: 100% !important;
max-width: 100% !important;
}
/* Mode toggle: slightly larger buttons for touch */
.mode-toggle button {
padding: 6px 14px !important;
font-size: 12px !important;
}
/* Vehicle selector dropdowns: stack on smaller tablets */
.vehicle-selector__inner,
.vehicle-selector .vs-group {
flex-wrap: wrap !important;
}
.vehicle-selector .vs-arrow {
display: none !important;
}
.vehicle-selector .vs-select {
min-width: 130px !important;
}
}
/* ── Phone portrait (< 768px) — single column, max simplification ── */
@media (max-width: 767px) {
.sidebar {
width: 85vw !important;
max-width: 300px !important;
}
.kpi-grid,
.nav-grid,
.results-grid {
grid-template-columns: 1fr !important;
}
.kpi-card__value {
font-size: 1.3rem !important;
}
/* Stack the mode toggle buttons vertically if tight */
.mode-toggle {
flex-wrap: wrap !important;
}
/* Hide non-essential UI to save space */
.header__store-badge,
.vs-vin-divider {
display: none !important;
}
/* Full-width modals */
.modal-content {
max-width: 95vw !important;
margin: var(--space-3) !important;
padding: var(--space-4) !important;
}
/* Tables: force readable font size */
table {
font-size: 12px !important;
}
table th,
table td {
padding: var(--space-2) var(--space-2) !important;
}
}
/* ── Landscape tablet (height < 600px with wide screen) ── */
@media (max-height: 600px) and (min-width: 768px) {
/* Reduce vertical padding for landscape tablet use */
.kpi-grid {
gap: var(--space-2) !important;
}
.dashboard,
.main-content,
.content {
padding: var(--space-3) !important;
}
}
/* ── Touch device hints ── */
@media (hover: none) and (pointer: coarse) {
/* Remove hover-only effects on touch devices — they cause sticky states */
.kpi-card:hover,
.nav-card:hover,
.part-card:hover,
.table-card:hover,
.card:hover {
transform: none !important;
}
/* Larger touch targets for interactive elements */
.sidebar__nav a,
.sidebar__nav-item,
.sidebar .nav-item {
padding: 12px 16px !important;
min-height: 48px !important;
display: flex !important;
align-items: center !important;
}
/* Scroll momentum on iOS */
.table-wrap,
.main-content,
.content,
.parts-grid,
.nav-grid {
-webkit-overflow-scrolling: touch;
}
/* Disable text selection on buttons (prevents accidental blue highlight on long tap) */
button,
.btn,
.nav-card,
.tab-btn {
-webkit-user-select: none;
user-select: none;
}
}
/* ==========================================================================
PRINT — Disable glass effects for printing
========================================================================== */
@media print {
.sidebar,
.theme-bar,
.kpi-card,
.table-card,
.card,
.modal,
.modal-content,
table thead th,
input,
select,
textarea {
background: #fff !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
box-shadow: none !important;
border-color: #ccc !important;
color: #000 !important;
}
}