/** * pos-ui.css — Nexus POS UI Polish Kit * Backlog visual improvements: skeletons, toasts, empty states, * scrollbars, focus rings, badges, tooltips, compact mode, etc. * Load AFTER tokens.css and common.css, BEFORE page-specific CSS. */ /* ═══════════════════════════════════════════════════════════════ 1. CUSTOM SCROLLBAR (global) ═══════════════════════════════════════════════════════════════ */ * { scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb, #444) var(--scrollbar-track, transparent); } *::-webkit-scrollbar { width: 6px; height: 6px; } *::-webkit-scrollbar-track { background: var(--scrollbar-track, transparent); } *::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb, #444); border-radius: var(--radius-full, 999px); } *::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover, #666); } /* ═══════════════════════════════════════════════════════════════ 2. SKELETON SCREENS ═══════════════════════════════════════════════════════════════ */ @keyframes skeleton-shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } .skeleton { background: linear-gradient(90deg, var(--color-surface-1, #1a1a1a) 25%, var(--color-surface-2, #2a2a2a) 50%, var(--color-surface-1, #1a1a1a) 75%); background-size: 200% 100%; animation: skeleton-shimmer 1.6s ease-in-out infinite; border-radius: var(--radius-md, 8px); pointer-events: none; user-select: none; } .skeleton--text { height: 1em; width: 100%; } .skeleton--text-sm { height: 0.75em; width: 60%; } .skeleton--circle { width: 40px; height: 40px; border-radius: var(--radius-full, 999px); } .skeleton--rect { height: 80px; width: 100%; } .skeleton--btn { height: 36px; width: 100px; border-radius: var(--radius-md, 8px); } .skeleton--table-row td { border: none !important; background: transparent !important; } .skeleton--table-row td .skeleton { height: 16px; } .skeleton--table-row td:nth-child(1) .skeleton { width: 40px; } .skeleton--table-row td:nth-child(2) .skeleton { width: 90%; } .skeleton--table-row td:nth-child(3) .skeleton { width: 70%; } .skeleton--table-row td:nth-child(4) .skeleton { width: 50%; } .skeleton--table-row td:nth-child(5) .skeleton { width: 60%; } /* ═══════════════════════════════════════════════════════════════ 3. EMPTY STATES (illustrated) ═══════════════════════════════════════════════════════════════ */ .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-8, 2rem); text-align: center; color: var(--color-text-muted, #888); } .empty-state__icon { width: 80px; height: 80px; margin-bottom: var(--space-4, 1rem); opacity: 0.4; color: var(--color-text-muted, #888); } .empty-state__icon svg { width: 100%; height: 100%; } .empty-state__title { font-size: var(--text-lg, 1.125rem); font-weight: var(--font-weight-bold, 700); color: var(--color-text-primary, #eee); margin-bottom: var(--space-2, 0.5rem); } .empty-state__subtitle { font-size: var(--text-sm, 0.875rem); max-width: 360px; line-height: 1.5; margin-bottom: var(--space-4, 1rem); } .empty-state__action { margin-top: var(--space-2, 0.5rem); } /* ═══════════════════════════════════════════════════════════════ 4. UNIFIED INPUT FOCUS RING ═══════════════════════════════════════════════════════════════ */ input:focus, select:focus, textarea:focus, .inv-field input:focus, .inv-field select:focus, .inv-field textarea:focus, .search-box:focus-within, .select-filter:focus, .form-control:focus { outline: none; border-color: var(--color-primary, #F5A623) !important; box-shadow: 0 0 0 3px var(--color-primary-muted, rgba(245,166,35,0.25)) !important; } input:disabled, select:disabled, textarea:disabled { opacity: 0.6; cursor: not-allowed; } /* ═══════════════════════════════════════════════════════════════ 5. BADGES (enhanced + new variants) ═══════════════════════════════════════════════════════════════ */ .badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: var(--radius-full, 999px); font-size: 0.6875rem; font-weight: var(--font-weight-bold, 700); letter-spacing: var(--tracking-wide, 0.05em); text-transform: uppercase; white-space: nowrap; line-height: 1.4; } .badge::before { content: ''; width: 6px; height: 6px; border-radius: var(--radius-full, 999px); background: currentColor; flex-shrink: 0; } .badge--ok { background: rgba(34, 197, 94, 0.12); color: var(--color-success, #22c55e); } .badge--low { background: rgba(239, 68, 68, 0.12); color: var(--color-error, #ef4444); } .badge--over { background: rgba(234, 179, 8, 0.12); color: var(--color-warning, #eab308); } .badge--pending { background: var(--color-primary-muted, rgba(245,166,35,0.15)); color: var(--color-primary, #F5A623); } .badge--complete { background: rgba(34, 197, 94, 0.12); color: var(--color-success, #22c55e); } .badge--transit { background: rgba(99, 102, 241, 0.12); color: #818cf8; } .badge--cancelled{ background: rgba(115, 115, 115, 0.12);color: var(--color-text-muted, #888); } .badge--damage { background: rgba(239, 68, 68, 0.12); color: var(--color-error, #ef4444); } .badge--shrinkage{ background: rgba(234, 179, 8, 0.12); color: var(--color-warning, #eab308); } .badge--correction{ background: var(--color-primary-muted, rgba(245,166,35,0.15)); color: var(--color-primary, #F5A623); } .badge--partial { background: rgba(234, 179, 8, 0.12); color: var(--color-warning, #eab308); } .badge--ml { background: rgba(255, 230, 0, 0.15); color: #2D3277; } .badge--ml::before { background: #2D3277; } .badge--new { background: rgba(59, 130, 246, 0.12); color: #3b82f6; } .badge--syncing { background: rgba(245, 166, 35, 0.12); color: var(--color-primary, #F5A623); animation: pulse-dot 1.5s ease-in-out infinite; } @keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } /* ═══════════════════════════════════════════════════════════════ 6. HOVER STATES (table + cards) ═══════════════════════════════════════════════════════════════ */ .data-table tbody tr { border-bottom: 1px solid var(--color-border, #2a2a2a); transition: background var(--duration-fast, 150ms) var(--ease-in-out, ease-in-out), transform var(--duration-fast, 150ms) var(--ease-in-out, ease-in-out); } .data-table tbody tr:hover { background: var(--color-surface-2, #222); transform: translateX(2px); } .data-table tbody tr:active { transform: translateX(0); } .card, .glass-card, .stat-card, .info-card { transition: transform var(--duration-fast, 150ms) var(--ease-in-out, ease-in-out), box-shadow var(--duration-fast, 150ms) var(--ease-in-out, ease-in-out); } .card:hover, .glass-card:hover, .stat-card:hover, .info-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg, 0 8px 24px rgba(0,0,0,0.3)); } /* ═══════════════════════════════════════════════════════════════ 7. TOAST NOTIFICATIONS (enhanced) ═══════════════════════════════════════════════════════════════ */ #toast-container { position: fixed; top: 16px; right: 16px; z-index: 9999; display: flex; flex-direction: column; gap: 8px; pointer-events: none; max-width: 420px; } .toast { display: flex; align-items: flex-start; gap: 10px; padding: 12px 16px; border-radius: var(--radius-lg, 12px); font-size: 14px; font-weight: 500; line-height: 1.4; box-shadow: 0 8px 24px rgba(0,0,0,0.25); pointer-events: auto; animation: toastSlideIn 0.35s cubic-bezier(0.16, 1, 0.3, 1); position: relative; overflow: hidden; backdrop-filter: blur(8px); border: 1px solid rgba(255,255,255,0.05); } .toast--ok { background: rgba(26, 122, 58, 0.95); color: #fff; } .toast--error { background: rgba(192, 57, 43, 0.95); color: #fff; } .toast--warn { background: rgba(212, 160, 23, 0.95); color: #000; } .toast--info { background: rgba(40, 40, 45, 0.95); color: #eee; border-color: rgba(255,255,255,0.08); } .toast__icon { flex-shrink: 0; width: 20px; height: 20px; margin-top: 1px; } .toast__content { flex: 1; } .toast__title { font-weight: 700; margin-bottom: 2px; font-size: 13px; } .toast__msg { font-size: 13px; opacity: 0.9; } .toast__action { margin-top: 8px; } .toast__action button { background: rgba(255,255,255,0.15); border: none; color: inherit; padding: 4px 10px; border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer; transition: background 0.15s; } .toast__action button:hover { background: rgba(255,255,255,0.25); } .toast__close { background: none; border: none; color: inherit; opacity: 0.6; cursor: pointer; font-size: 16px; line-height: 1; padding: 0; margin-left: 4px; flex-shrink: 0; } .toast__close:hover { opacity: 1; } .toast__progress { position: absolute; bottom: 0; left: 0; height: 3px; background: rgba(255,255,255,0.4); border-radius: 0 0 0 var(--radius-lg, 12px); animation: toastProgress linear forwards; } @keyframes toastSlideIn { from { opacity: 0; transform: translateX(40px) scale(0.95); } to { opacity: 1; transform: translateX(0) scale(1); } } @keyframes toastSlideOut { from { opacity: 1; transform: translateX(0) scale(1); } to { opacity: 0; transform: translateX(40px) scale(0.95); } } @keyframes toastProgress { from { width: 100%; } to { width: 0%; } } /* ═══════════════════════════════════════════════════════════════ 8. TOOLTIPS ═══════════════════════════════════════════════════════════════ */ [data-tooltip] { position: relative; cursor: help; } [data-tooltip]::after { content: attr(data-tooltip); position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%) scale(0.9); padding: 6px 10px; background: var(--color-surface-3, #333); color: var(--color-text-primary, #eee); font-size: 12px; font-weight: 500; white-space: nowrap; border-radius: var(--radius-md, 8px); box-shadow: var(--shadow-md, 0 4px 12px rgba(0,0,0,0.2)); opacity: 0; pointer-events: none; transition: opacity 0.15s, transform 0.15s; z-index: 10000; border: 1px solid var(--color-border, #2a2a2a); } [data-tooltip]:hover::after { opacity: 1; transform: translateX(-50%) scale(1); } [data-tooltip-pos="bottom"]::after { bottom: auto; top: calc(100% + 6px); } [data-tooltip-pos="left"]::after { bottom: auto; left: auto; right: calc(100% + 6px); top: 50%; transform: translateY(-50%) scale(0.9); } [data-tooltip-pos="left"]:hover::after { transform: translateY(-50%) scale(1); } [data-tooltip-pos="right"]::after { bottom: auto; left: calc(100% + 6px); top: 50%; transform: translateY(-50%) scale(0.9); } [data-tooltip-pos="right"]:hover::after { transform: translateY(-50%) scale(1); } /* ═══════════════════════════════════════════════════════════════ 9. COMPACT / DENSE MODE ═══════════════════════════════════════════════════════════════ */ [data-density="compact"] .data-table th, [data-density="compact"] .data-table td { padding-top: 6px; padding-bottom: 6px; font-size: 0.8125rem; } [data-density="compact"] .data-table tbody tr { height: 36px; } [data-density="compact"] .sidebar__nav-link { padding: 8px 14px; } [data-density="compact"] .card, [data-density="compact"] .glass-card { padding: var(--space-3, 0.75rem); } [data-density="compact"] .form-group { margin-bottom: var(--space-2, 0.5rem); } /* ═══════════════════════════════════════════════════════════════ 10. STICKY TABLE HEADERS ═══════════════════════════════════════════════════════════════ */ .data-table thead { position: sticky; top: 0; z-index: 10; } .data-table thead th { position: sticky; top: 0; background: var(--color-surface-1, #1a1a1a); z-index: 10; } /* ═══════════════════════════════════════════════════════════════ 11. RESIZABLE COLUMNS (visual cue) ═══════════════════════════════════════════════════════════════ */ .data-table th { position: relative; user-select: none; } .data-table th .resize-handle { position: absolute; right: 0; top: 0; bottom: 0; width: 4px; cursor: col-resize; background: transparent; transition: background 0.15s; } .data-table th .resize-handle:hover, .data-table th.is-resizing .resize-handle { background: var(--color-primary, #F5A623); } /* ═══════════════════════════════════════════════════════════════ 12. BREADCRUMBS ═══════════════════════════════════════════════════════════════ */ .breadcrumbs { display: flex; align-items: center; gap: var(--space-2, 0.5rem); padding: var(--space-2, 0.5rem) var(--space-4, 1rem); font-size: 0.8125rem; color: var(--color-text-muted, #888); border-bottom: 1px solid var(--color-border, #2a2a2a); } .breadcrumbs a { color: var(--color-text-secondary, #aaa); text-decoration: none; transition: color 0.15s; } .breadcrumbs a:hover { color: var(--color-primary, #F5A623); } .breadcrumbs__sep { opacity: 0.4; } .breadcrumbs__current { color: var(--color-text-primary, #eee); font-weight: var(--font-weight-semibold, 600); } /* ═══════════════════════════════════════════════════════════════ 13. USER AVATARS (initials) ═══════════════════════════════════════════════════════════════ */ .avatar { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: var(--radius-full, 999px); font-size: 14px; font-weight: var(--font-weight-bold, 700); color: #fff; background: var(--color-primary, #F5A623); flex-shrink: 0; } .avatar--sm { width: 28px; height: 28px; font-size: 12px; } .avatar--lg { width: 48px; height: 48px; font-size: 18px; } .avatar--circle { border-radius: var(--radius-full, 999px); } /* ═══════════════════════════════════════════════════════════════ 14. CONNECTION INDICATOR ═══════════════════════════════════════════════════════════════ */ .connection-indicator { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: var(--radius-full, 999px); background: var(--color-surface-2, #222); } .connection-indicator::before { content: ''; width: 8px; height: 8px; border-radius: var(--radius-full, 999px); background: var(--color-success, #22c55e); box-shadow: 0 0 6px var(--color-success, #22c55e); } .connection-indicator--offline::before { background: var(--color-error, #ef4444); box-shadow: 0 0 6px var(--color-error, #ef4444); } .connection-indicator--syncing::before { background: var(--color-primary, #F5A623); animation: pulse-dot 1.5s ease-in-out infinite; } /* ═══════════════════════════════════════════════════════════════ 15. NOTIFICATIONS DROPDOWN ═══════════════════════════════════════════════════════════════ */ .notif-dropdown { position: absolute; top: calc(100% + 8px); right: 0; width: 360px; max-height: 480px; background: var(--color-surface-1, #1a1a1a); border: 1px solid var(--color-border, #2a2a2a); border-radius: var(--radius-lg, 12px); box-shadow: var(--shadow-lg, 0 8px 24px rgba(0,0,0,0.3)); z-index: 1000; overflow: hidden; display: flex; flex-direction: column; } .notif-dropdown__header { padding: 12px 16px; border-bottom: 1px solid var(--color-border, #2a2a2a); font-weight: 700; font-size: 14px; display: flex; justify-content: space-between; align-items: center; } .notif-dropdown__list { overflow-y: auto; flex: 1; } .notif-dropdown__item { padding: 12px 16px; border-bottom: 1px solid var(--color-border, #2a2a2a); display: flex; gap: 12px; align-items: flex-start; cursor: pointer; transition: background 0.15s; } .notif-dropdown__item:hover { background: var(--color-surface-2, #222); } .notif-dropdown__item--unread { border-left: 3px solid var(--color-primary, #F5A623); } .notif-dropdown__icon { flex-shrink: 0; width: 32px; height: 32px; border-radius: var(--radius-md, 8px); display: flex; align-items: center; justify-content: center; background: var(--color-surface-2, #222); font-size: 14px; } .notif-dropdown__content { flex: 1; } .notif-dropdown__title { font-size: 13px; font-weight: 600; color: var(--color-text-primary, #eee); margin-bottom: 2px; } .notif-dropdown__time { font-size: 11px; color: var(--color-text-muted, #888); } .notif-dropdown__empty { padding: 24px; text-align: center; color: var(--color-text-muted, #888); font-size: 13px; } /* ═══════════════════════════════════════════════════════════════ 16. CMD+K SEARCH OVERLAY ═══════════════════════════════════════════════════════════════ */ .cmdk-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.6); backdrop-filter: blur(4px); z-index: 10000; display: flex; align-items: flex-start; justify-content: center; padding-top: 15vh; opacity: 0; transition: opacity 0.2s; pointer-events: none; } .cmdk-overlay.is-open { opacity: 1; pointer-events: auto; } .cmdk-modal { width: 640px; max-width: 90vw; background: var(--color-surface-1, #1a1a1a); border: 1px solid var(--color-border, #2a2a2a); border-radius: var(--radius-xl, 16px); box-shadow: var(--shadow-xl, 0 16px 48px rgba(0,0,0,0.4)); overflow: hidden; transform: scale(0.95); transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1); } .cmdk-overlay.is-open .cmdk-modal { transform: scale(1); } .cmdk-input-wrap { display: flex; align-items: center; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--color-border, #2a2a2a); } .cmdk-input { flex: 1; background: transparent; border: none; color: var(--color-text-primary, #eee); font-size: 16px; outline: none; } .cmdk-input::placeholder { color: var(--color-text-muted, #888); } .cmdk-shortcut { font-size: 11px; color: var(--color-text-muted, #888); background: var(--color-surface-2, #222); padding: 2px 6px; border-radius: 4px; } .cmdk-results { max-height: 400px; overflow-y: auto; } .cmdk-group { padding: 8px 0; } .cmdk-group__label { padding: 4px 20px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-text-muted, #888); } .cmdk-item { display: flex; align-items: center; gap: 12px; padding: 10px 20px; cursor: pointer; transition: background 0.12s; font-size: 14px; } .cmdk-item:hover, .cmdk-item.is-selected { background: var(--color-surface-2, #222); } .cmdk-item__icon { width: 28px; height: 28px; border-radius: var(--radius-md, 8px); display: flex; align-items: center; justify-content: center; background: var(--color-surface-2, #222); font-size: 13px; } .cmdk-item__meta { margin-left: auto; font-size: 11px; color: var(--color-text-muted, #888); } .cmdk-footer { padding: 8px 20px; border-top: 1px solid var(--color-border, #2a2a2a); font-size: 11px; color: var(--color-text-muted, #888); display: flex; justify-content: space-between; } /* ═══════════════════════════════════════════════════════════════ 17. ENTRANCE ANIMATIONS ═══════════════════════════════════════════════════════════════ */ @keyframes fadeInUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes scaleIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } .animate-fade-in-up { animation: fadeInUp 0.4s cubic-bezier(0.16, 1, 0.3, 1) both; } .animate-fade-in { animation: fadeIn 0.3s ease both; } .animate-scale-in { animation: scaleIn 0.3s cubic-bezier(0.16, 1, 0.3, 1) both; } /* Stagger delays */ .stagger-1 { animation-delay: 0.05s; } .stagger-2 { animation-delay: 0.10s; } .stagger-3 { animation-delay: 0.15s; } .stagger-4 { animation-delay: 0.20s; } .stagger-5 { animation-delay: 0.25s; } /* ═══════════════════════════════════════════════════════════════ 18. SPARKLINE (mini charts) ═══════════════════════════════════════════════════════════════ */ .sparkline { display: flex; align-items: flex-end; gap: 2px; height: 24px; } .sparkline__bar { flex: 1; border-radius: 1px; background: var(--color-primary, #F5A623); opacity: 0.6; transition: opacity 0.15s; min-width: 3px; } .sparkline__bar:hover { opacity: 1; } .sparkline--up .sparkline__bar { background: var(--color-success, #22c55e); } .sparkline--down .sparkline__bar { background: var(--color-error, #ef4444); } /* ═══════════════════════════════════════════════════════════════ 19. SYNC SPINNER / ANIMATED ICONS ═══════════════════════════════════════════════════════════════ */ @keyframes spin-slow { to { transform: rotate(360deg); } } @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } } .icon-spin { animation: spin-slow 1.2s linear infinite; } .icon-bounce { animation: bounce 1s ease-in-out infinite; } .icon-pulse { animation: pulse-dot 1.5s ease-in-out infinite; } /* ═══════════════════════════════════════════════════════════════ 20. KIOSK / TOUCH MODE ═══════════════════════════════════════════════════════════════ */ [data-touch="true"] .data-table th, [data-touch="true"] .data-table td { padding: 16px 14px; font-size: 1rem; } [data-touch="true"] .btn { padding: 14px 24px; font-size: 1rem; min-height: 48px; } [data-touch="true"] .sidebar__nav-link { padding: 16px 18px; font-size: 1rem; } [data-touch="true"] input, [data-touch="true"] select, [data-touch="true"] textarea { font-size: 16px; padding: 14px 12px; } [data-touch="true"] .search-box { min-height: 48px; } /* ═══════════════════════════════════════════════════════════════ 21. BULK ACTIONS TOOLBAR ═══════════════════════════════════════════════════════════════ */ .bulk-toolbar { display: flex; align-items: center; gap: var(--space-3, 0.75rem); padding: var(--space-3, 0.75rem) var(--space-4, 1rem); background: var(--color-surface-2, #222); border: 1px solid var(--color-border, #2a2a2a); border-radius: var(--radius-lg, 12px); margin-bottom: var(--space-4, 1rem); animation: fadeInUp 0.25s ease both; } .bulk-toolbar__count { font-size: 13px; font-weight: 600; color: var(--color-text-primary, #eee); padding-right: var(--space-3, 0.75rem); border-right: 1px solid var(--color-border, #2a2a2a); } .bulk-toolbar__actions { display: flex; gap: var(--space-2, 0.5rem); } /* ═══════════════════════════════════════════════════════════════ 22. TICKET PREVIEW ═══════════════════════════════════════════════════════════════ */ .ticket-preview { background: #fff; color: #222; padding: 24px; border-radius: var(--radius-md, 8px); font-family: 'Courier New', monospace; font-size: 12px; line-height: 1.6; max-width: 320px; margin: 0 auto; box-shadow: 0 4px 12px rgba(0,0,0,0.15); } .ticket-preview__header { text-align: center; border-bottom: 1px dashed #ccc; padding-bottom: 12px; margin-bottom: 12px; } .ticket-preview__title { font-size: 16px; font-weight: 700; margin-bottom: 4px; } .ticket-preview__meta { font-size: 11px; color: #666; } .ticket-preview__row { display: flex; justify-content: space-between; margin-bottom: 4px; } .ticket-preview__total { border-top: 1px dashed #ccc; padding-top: 8px; margin-top: 8px; font-size: 14px; font-weight: 700; } /* ═══════════════════════════════════════════════════════════════ 23. IMAGE COMPARATOR ═══════════════════════════════════════════════════════════════ */ .img-compare { position: relative; overflow: hidden; border-radius: var(--radius-lg, 12px); user-select: none; } .img-compare__img { width: 100%; display: block; } .img-compare__overlay { position: absolute; top: 0; left: 0; bottom: 0; width: 50%; overflow: hidden; border-right: 2px solid var(--color-primary, #F5A623); } .img-compare__overlay img { height: 100%; width: auto; max-width: none; } .img-compare__handle { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 36px; height: 36px; background: var(--color-primary, #F5A623); border-radius: var(--radius-full, 999px); display: flex; align-items: center; justify-content: center; cursor: ew-resize; box-shadow: 0 2px 8px rgba(0,0,0,0.3); font-size: 14px; color: #fff; } /* ═══════════════════════════════════════════════════════════════ 24. CUSTOM LOADER / SPINNER ═══════════════════════════════════════════════════════════════ */ .nx-loader { position: relative; width: 48px; height: 48px; } .nx-loader__ring { position: absolute; inset: 0; border: 3px solid transparent; border-top-color: var(--color-primary, #F5A623); border-radius: 50%; animation: spin-slow 1s linear infinite; } .nx-loader__ring:nth-child(2) { inset: 6px; border-top-color: var(--color-secondary, #3b82f6); animation-duration: 1.3s; animation-direction: reverse; } .nx-loader__ring:nth-child(3) { inset: 12px; border-top-color: var(--color-success, #22c55e); animation-duration: 0.8s; } .nx-loader--sm { width: 24px; height: 24px; } .nx-loader--sm .nx-loader__ring { border-width: 2px; } .nx-loader--sm .nx-loader__ring:nth-child(2) { inset: 4px; } .nx-loader--sm .nx-loader__ring:nth-child(3) { inset: 8px; } /* ═══════════════════════════════════════════════════════════════ 25. SAVED FILTERS CHIPS ═══════════════════════════════════════════════════════════════ */ .filter-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; background: var(--color-surface-2, #222); border: 1px solid var(--color-border, #2a2a2a); border-radius: var(--radius-full, 999px); font-size: 12px; font-weight: 500; color: var(--color-text-secondary, #aaa); cursor: pointer; transition: all 0.15s; } .filter-chip:hover { border-color: var(--color-primary, #F5A623); color: var(--color-text-primary, #eee); } .filter-chip.is-active { background: var(--color-primary-muted, rgba(245,166,35,0.15)); border-color: var(--color-primary, #F5A623); color: var(--color-primary, #F5A623); } .filter-chip__remove { background: none; border: none; color: inherit; cursor: pointer; font-size: 14px; line-height: 1; padding: 0; opacity: 0.6; } .filter-chip__remove:hover { opacity: 1; } /* ═══════════════════════════════════════════════════════════════ 26. DARK MODE REFINEMENTS (subtle borders, depth) ═══════════════════════════════════════════════════════════════ */ [data-theme="modern"] .data-table thead th { background: linear-gradient(180deg, var(--color-surface-1, #1a1a1a) 0%, var(--color-surface-2, #222) 100%); } [data-theme="modern"] .card, [data-theme="modern"] .glass-card { border: 1px solid rgba(255,255,255,0.04); } [data-theme="industrial"] .data-table thead th { background: var(--color-surface-1, #1a1a1a); border-bottom: 2px solid var(--color-primary, #F5A623); }