/* Modern Tailwind-like Dark Theme */ :root { --bg-base: #0f172a; /* slate-900 */ --bg-sidebar: #1e293b; /* slate-800 */ --bg-card: #1e293b; /* slate-800 */ --bg-hover: #334155; /* slate-700 */ --border-color: #334155; /* slate-700 */ --text-main: #f8fafc; /* slate-50 */ --text-muted: #94a3b8; /* slate-400 */ --primary: #3b82f6; /* blue-500 */ --primary-hover: #2563eb; /* blue-600 */ --success: #10b981; /* emerald-500 */ --warning: #f59e0b; /* amber-500 */ --danger: #ef4444; /* red-500 */ --radius-lg: 16px; --radius-md: 10px; --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: "Outfit", sans-serif; background: var(--bg-base); color: var(--text-main); height: 100vh; overflow: hidden; } /* Layout */ .app-layout { display: flex; height: 100vh; width: 100vw; } /* Sidebar */ .sidebar { width: 260px; background: var(--bg-sidebar); border-right: 1px solid var(--border-color); display: flex; flex-direction: column; transition: transform 0.3s ease; z-index: 100; } .sidebar-brand { height: 70px; display: flex; align-items: center; padding: 0 1.5rem; gap: 0.75rem; border-bottom: 1px solid var(--border-color); } .brand-icon { width: 36px; height: 36px; background: linear-gradient(135deg, var(--primary), #8b5cf6); border-radius: 10px; display: flex; justify-content: center; align-items: center; font-size: 1.1rem; color: #fff; box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); } .brand-text { font-size: 1.25rem; font-weight: 700; color: #fff; letter-spacing: 0.5px; } .brand-text span { color: var(--primary); } .close-sidebar { display: none; background: none; border: none; color: var(--text-muted); font-size: 1.2rem; cursor: pointer; margin-left: auto; } .sidebar-menu { padding: 1.5rem 1rem; flex: 1; } .menu-label { font-size: 0.75rem; font-weight: 700; color: var(--text-muted); margin-bottom: 1rem; padding-left: 0.5rem; letter-spacing: 1px; } .menu-item { display: flex; align-items: center; gap: 1rem; padding: 0.8rem 1rem; color: var(--text-muted); text-decoration: none; border-radius: var(--radius-md); transition: all 0.2s; font-weight: 500; margin-bottom: 0.5rem; } .menu-item i { font-size: 1.1rem; width: 20px; text-align: center; } .menu-item:hover { background: var(--bg-hover); color: var(--text-main); } .menu-item.active { background: rgba(59, 130, 246, 0.1); color: var(--primary); } .sidebar-footer { padding: 1.5rem; border-top: 1px solid var(--border-color); } .version-badge { background: var(--bg-hover); color: var(--text-muted); padding: 0.4rem 0.8rem; border-radius: 20px; font-size: 0.8rem; text-align: center; font-weight: 600; } /* Main Content */ .main-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; } /* Top Header */ .topheader { height: 70px; background: rgba(15, 23, 42, 0.9); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid rgba(255,255,255,0.03); display: flex; justify-content: space-between; align-items: center; padding: 0 2.5rem; } .header-left { display: flex; align-items: center; gap: 1rem; } .menu-toggle { display: none; background: var(--bg-hover); border: 1px solid var(--border-color); color: var(--text-main); width: 40px; height: 40px; border-radius: var(--radius-md); cursor: pointer; } .page-title { font-size: 1.25rem; font-weight: 600; color: #fff; } .session-control { display: flex; align-items: center; gap: 1.5rem; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.05); padding: 0.4rem 0.4rem 0.4rem 1.2rem; border-radius: 50px; } .session-status { display: flex; align-items: center; gap: 0.8rem; } .indicator-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--text-muted); } .indicator-dot.active { background: var(--success); box-shadow: 0 0 10px var(--success); animation: pulse 2s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); } 70% { box-shadow: 0 0 0 8px rgba(16, 185, 129, 0); } 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); } } .status-text { display: flex; flex-direction: column; } .indicator-text { font-size: 0.75rem; font-weight: 600; color: var(--text-muted); text-transform: uppercase; } .indicator-text.active { color: var(--success); } .session-timer { font-size: 0.9rem; font-weight: 700; font-variant-numeric: tabular-nums; } .btn-sorting { background: var(--success); color: #fff; border: none; padding: 0.6rem 1.2rem; border-radius: 30px; font-family: "Outfit"; font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 0.5rem; transition: all 0.3s; } .btn-sorting:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); } .btn-sorting.btn-stop { background: var(--danger); } .btn-sorting.btn-stop:hover:not(:disabled) { box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3); } .btn-sorting:disabled { opacity: 0.6; cursor: not-allowed; } /* Body Content */ .content-body { flex: 1; overflow-y: auto; padding: 2rem; display: flex; flex-direction: column; gap: 2rem; } /* Cards Grid */ .cards-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem; } .stat-card { background: linear-gradient(145deg, rgba(30, 41, 59, 1), rgba(15, 23, 42, 1)); border: 1px solid rgba(255,255,255,0.05); border-radius: var(--radius-lg); padding: 1.8rem 1.5rem; display: flex; align-items: center; gap: 1.2rem; transition: transform 0.3s; box-shadow: var(--shadow-md); } .stat-card:hover { transform: translateY(-3px); } .card-icon { width: 54px; height: 54px; /* border-radius: 14px; */ display: flex; justify-content: center; align-items: center; font-size: 1.5rem; } .card-icon img { width: 48px; height: 48px; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2)); } .card-icon.raw { /* removed background */ color: var(--success); } .card-icon.ripe { /* removed background */ color: var(--warning); } .card-info { flex: 1; } .card-label { font-size: 0.85rem; color: var(--text-muted); font-weight: 500; margin-bottom: 0.2rem; } .card-value { font-size: 2.2rem; font-weight: 700; color: #fff; } .card-value small { font-size: 1rem; color: var(--text-muted); font-weight: 500; } .text-warning { color: var(--warning) !important; } /* Sections */ .section-container { background: var(--bg-sidebar); border: 1px solid rgba(255,255,255,0.04); border-radius: var(--radius-lg); overflow: visible; box-shadow: 0 10px 30px rgba(0,0,0,0.2); margin-bottom: 2rem; display: flex; flex-direction: column; } .section-header { display: flex; justify-content: space-between; align-items: center; padding: 1.5rem 1.8rem; border-bottom: 1px solid rgba(255,255,255,0.04); background: transparent; } .section-title { font-size: 1.2rem; font-weight: 700; display: flex; align-items: center; gap: 0.8rem; color: #fff; letter-spacing: 0.5px; } .section-title i { color: var(--primary); } .section-actions { display: flex; align-items: center; gap: 0.8rem; } .flex-wrap { flex-wrap: wrap; } /* Filter Bar */ .filter-bar { display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap; } .filter-tabs { display: flex; background: var(--bg-base); border: 1px solid var(--border-color); border-radius: 8px; padding: 3px; } .filter-tab { background: transparent; border: none; color: var(--text-muted); padding: 0.4rem 0.8rem; border-radius: 6px; font-family: "Outfit"; font-size: 0.8rem; font-weight: 500; cursor: pointer; transition: all 0.2s; } .filter-tab:hover { color: #fff; } .filter-tab.active { background: var(--bg-hover); color: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); } .filter-extra { display: flex; align-items: center; gap: 0.5rem; } .date-input { background: var(--bg-base); border: 1px solid var(--border-color); color: #fff; font-family: "Outfit"; font-size: 0.8rem; padding: 0.45rem 0.8rem; border-radius: 8px; outline: none; } .date-input:focus { border-color: var(--primary); } .date-input::-webkit-calendar-picker-indicator { filter: invert(0.8); cursor: pointer; } .filter-session-select { max-width: 200px; } .select-label { width: 140px; } .custom-date-range { display: flex; align-items: center; gap: 0.4rem; } .custom-date-range span { color: var(--text-muted); } .btn-primary { background: var(--primary); color: #fff; border: none; border-radius: 8px; font-family: "Outfit"; cursor: pointer; transition: background 0.2s; } .btn-primary:hover { background: var(--primary-hover); } .btn-sm { padding: 0.45rem 0.7rem; } .btn-icon { background: var(--bg-base); border: 1px solid var(--border-color); color: var(--text-muted); width: 34px; height: 34px; border-radius: 8px; cursor: pointer; display: flex; justify-content: center; align-items: center; transition: all 0.2s; } .btn-icon:hover { background: var(--bg-hover); color: var(--primary); } /* Table */ .table-wrapper { overflow-x: auto; width: 100%; padding-bottom: 1rem; } .data-table { width: 100%; border-collapse: collapse; text-align: left; } .data-table th { padding: 1.2rem 1.8rem; font-size: 0.85rem; font-weight: 600; color: var(--text-muted); border-bottom: 1px solid rgba(255,255,255,0.04); white-space: nowrap; text-transform: uppercase; letter-spacing: 0.5px; } .data-table td { padding: 1.2rem 1.8rem; font-size: 0.95rem; border-bottom: 1px solid rgba(255, 255, 255, 0.02); color: #f8fafc; } .data-table tr:last-child td { border-bottom: none; } .data-table tbody tr:hover { background: rgba(255, 255, 255, 0.015); } .empty-state { text-align: center; padding: 3rem !important; color: var(--text-muted); font-style: italic; } /* Foto Grid */ .foto-grid { padding: 1.5rem; display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1.2rem; } .foto-empty { grid-column: 1 / -1; text-align: center; padding: 2rem; color: var(--text-muted); font-style: italic; } .foto-card { background: var(--bg-base); border: 1px solid var(--border-color); border-radius: 12px; overflow: hidden; cursor: pointer; transition: transform 0.2s, border-color 0.2s; } .foto-card:hover { transform: translateY(-4px); border-color: var(--primary); } .foto-card img { width: 100%; height: 160px; object-fit: cover; border-bottom: 1px solid var(--border-color); } .foto-card-info { padding: 0.8rem; display: flex; flex-direction: column; gap: 0.4rem; } .foto-card-label { font-size: 0.75rem; font-weight: 600; padding: 0.2rem 0.6rem; border-radius: 4px; display: inline-block; width: fit-content; text-transform: uppercase; } .foto-card-label.matang { background: rgba(245, 158, 11, 0.15); color: var(--warning); } .foto-card-label.mentah { background: rgba(16, 185, 129, 0.15); color: var(--success); } .foto-card-time { font-size: 0.75rem; color: var(--text-muted); } /* Modals */ .modal-overlay, .foto-modal-overlay { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(15, 23, 42, 0.8); backdrop-filter: blur(4px); display: flex; justify-content: center; align-items: center; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.3s; } .modal-overlay.show, .foto-modal-overlay.show { opacity: 1; visibility: visible; } .modal-dialog { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--radius-lg); padding: 2rem; max-width: 400px; width: 90%; text-align: center; transform: scale(0.95); transition: transform 0.3s; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); } .modal-overlay.show .modal-dialog { transform: scale(1); } .modal-icon-wrap { width: 64px; height: 64px; border-radius: 50%; display: flex; justify-content: center; align-items: center; margin: 0 auto 1.2rem; font-size: 2rem; } .modal-icon-wrap.warning { background: rgba(239, 68, 68, 0.1); color: var(--danger); } .modal-title { font-size: 1.25rem; font-weight: 600; margin-bottom: 0.5rem; } .modal-desc { color: var(--text-muted); font-size: 0.9rem; line-height: 1.5; margin-bottom: 1.5rem; } .modal-actions { display: flex; gap: 1rem; } .modal-actions button { flex: 1; padding: 0.6rem; border: none; border-radius: 8px; font-family: "Outfit"; font-weight: 600; cursor: pointer; transition: background 0.2s; } .btn-secondary { background: var(--bg-hover); color: #fff; } .btn-secondary:hover { background: #475569; } .btn-danger { background: var(--danger); color: #fff; } .btn-danger:hover { background: #dc2626; } .foto-modal-box { position: relative; max-width: 800px; width: 90%; background: var(--bg-card); border-radius: var(--radius-lg); overflow: hidden; border: 1px solid var(--border-color); box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); transform: translateY(20px); transition: transform 0.3s; } .foto-modal-overlay.show .foto-modal-box { transform: translateY(0); } .foto-modal-close { position: absolute; top: 1rem; right: 1rem; background: rgba(0, 0, 0, 0.5); color: #fff; border: none; width: 36px; height: 36px; border-radius: 50%; font-size: 1.2rem; cursor: pointer; z-index: 10; transition: background 0.2s; } .foto-modal-close:hover { background: rgba(239, 68, 68, 0.8); } .foto-modal-box img { width: 100%; height: auto; display: block; max-height: 70vh; object-fit: contain; background: #000; } .foto-modal-info { padding: 1rem 1.5rem; display: flex; justify-content: space-between; align-items: center; background: var(--bg-card); } .foto-badge { font-weight: 600; text-transform: uppercase; color: #fff; } .foto-time { color: var(--text-muted); font-size: 0.9rem; } /* Toasts */ .toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 1050; display: flex; flex-direction: column; gap: 10px; } .toast { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 10px; padding: 1rem; width: 320px; display: flex; gap: 1rem; align-items: flex-start; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.4); animation: slideIn 0.3s ease; position: relative; overflow: hidden; } .toast-out { animation: slideOut 0.3s ease forwards; } @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes slideOut { to { transform: translateX(100%); opacity: 0; } } .toast-icon { font-size: 1.5rem; } .toast-success .toast-icon { color: var(--success); } .toast-error .toast-icon { color: var(--danger); } .toast-info .toast-icon { color: var(--primary); } .toast-body { flex: 1; } .toast-title { font-weight: 600; margin-bottom: 0.2rem; font-size: 0.95rem; } .toast-message { font-size: 0.85rem; color: var(--text-muted); line-height: 1.4; } .toast-close { background: none; border: none; color: var(--text-muted); cursor: pointer; } .toast-close:hover { color: #fff; } /* Responsive */ @media (max-width: 1024px) { .cards-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 768px) { .sidebar { position: fixed; transform: translateX(-100%); height: 100%; box-shadow: 10px 0 25px rgba(0, 0, 0, 0.5); } .sidebar.active { transform: translateX(0); } .close-sidebar { display: block; } .menu-toggle { display: block; } .topheader { padding: 0 1.2rem; } .page-title { display: none; } .content-body { padding: 1.2rem; } .cards-grid { grid-template-columns: 1fr; } .session-control { padding: 0.3rem 0.3rem 0.3rem 1rem; gap: 1rem; } .btn-sorting { padding: 0.5rem 1rem; font-size: 0.9rem; } .filter-bar { width: 100%; } .section-actions { flex-direction: column; align-items: flex-start; } .filter-tabs { flex-wrap: wrap; } } /* Fix Flex Shrink Issues */ .cards-grid, .section-container { flex-shrink: 0; } /* Summary Section */ .summary-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1rem; padding: 1.5rem; } .summary-item { background: var(--bg-base); border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 1rem; display: flex; flex-direction: column; gap: 0.5rem; align-items: center; text-align: center; } .summary-label { font-size: 0.75rem; color: var(--text-muted); font-weight: 600; text-transform: uppercase; } .summary-value { font-size: 1.25rem; font-weight: 700; color: #fff; } .summary-value small { font-size: 0.8rem; color: var(--text-muted); font-weight: 500; } .summary-item.highlight { border-color: var(--primary); background: rgba(59, 130, 246, 0.05); } .summary-item.highlight-alt { border-color: var(--success); background: rgba(16, 185, 129, 0.05); } @media (max-width: 1024px) { .summary-grid { grid-template-columns: repeat(3, 1fr); } } @media (max-width: 640px) { .summary-grid { grid-template-columns: repeat(2, 1fr); } }