diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..1a004cf --- /dev/null +++ b/styles.css @@ -0,0 +1,814 @@ +/* ============================================================= + styles.css — Стили приложения «Сверка выручки водителей» + ============================================================= */ + +/* ---------- Переменные и тема ---------- */ +:root { + --primary: #6366f1; + --primary-dark: #4f46e5; + --primary-light: #a5b4fc; + --bg-start: #4f46e5; + --bg-end: #7c3aed; + --surface: #ffffff; + --surface-alt: #f8fafc; + --text: #1e293b; + --text-secondary: #64748b; + --text-muted: #94a3b8; + --border: #e2e8f0; + --success: #10b981; + --success-bg: #d1fae5; + --success-text: #065f46; + --warning: #f59e0b; + --warning-bg: #fef3c7; + --warning-text: #92400e; + --danger: #ef4444; + --danger-bg: #fee2e2; + --danger-text: #991b1b; + --radius: 16px; + --radius-sm: 8px; + --radius-xs: 6px; + --shadow-md: 0 4px 20px rgba(0, 0, 0, 0.1); + --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.12); + --transition: 0.25s cubic-bezier(0.4, 0, 0.2, 1); +} + +[data-theme="dark"] { + --bg-start: #111827; + --bg-end: #1e293b; + --surface: #1f2937; + --surface-alt: #111827; + --text: #f9fafb; + --text-secondary: #d1d5db; + --text-muted: #9ca3af; + --border: #374151; + --success-bg: #064e3b; + --success-text: #6ee7b7; + --warning-bg: #78350f; + --warning-text: #fcd34d; + --danger-bg: #7f1d1d; + --danger-text: #fca5a5; +} + +/* ---------- Базовые стили ---------- */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + 'Helvetica Neue', Arial, sans-serif; + background: linear-gradient(160deg, var(--bg-start) 0%, var(--bg-end) 50%, #a855f7 100%); + min-height: 100vh; + color: var(--text); + line-height: 1.6; + -webkit-font-smoothing: antialiased; +} + +/* ---------- Контейнер ---------- */ +.container { + max-width: 1100px; + margin: 0 auto; + padding: 2rem 1.5rem 4rem; + position: relative; + z-index: 1; +} + +/* ---------- Hero ---------- */ +.hero { + text-align: center; + padding: 2rem 1rem 3rem; + color: white; +} + +.hero-badge { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: rgba(255, 255, 255, 0.15); + backdrop-filter: blur(10px); + padding: 0.4rem 1rem; + border-radius: 20px; + font-size: 0.85rem; + font-weight: 500; + margin-bottom: 1.25rem; + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.hero h1 { + font-size: clamp(1.8rem, 4vw, 2.75rem); + font-weight: 800; + letter-spacing: -0.02em; + margin-bottom: 0.75rem; + text-shadow: 0 2px 10px rgba(0, 0, 0, 0.15); +} + +.hero-subtitle { + font-size: 1.05rem; + opacity: 0.9; + max-width: 650px; + margin: 0 auto; + line-height: 1.7; +} + +/* ---------- Карточки ---------- */ +.card { + background: var(--surface); + border-radius: var(--radius); + box-shadow: var(--shadow-lg); + margin-bottom: 1.5rem; + overflow: hidden; + transition: box-shadow var(--transition); +} + +.card:hover { + box-shadow: 0 15px 50px rgba(0, 0, 0, 0.15); +} + +.card-head { + display: flex; + align-items: center; + gap: 1rem; + padding: 1.25rem 2rem; + border-bottom: 1px solid var(--border); + background: var(--surface-alt); +} + +.step-badge { + width: 36px; + height: 36px; + border-radius: 10px; + background: linear-gradient(135deg, var(--primary), var(--bg-end)); + color: white; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 1rem; + flex-shrink: 0; +} + +.card-head h2 { + font-size: 1.25rem; + font-weight: 700; +} + +.card-body { + padding: 2rem; +} + +/* ---------- Dropzone ---------- */ +.dropzone { + border: 2px dashed var(--border); + border-radius: 12px; + padding: 3rem 2rem; + text-align: center; + cursor: pointer; + transition: all var(--transition); + background: var(--surface-alt); +} + +.dropzone:hover, +.dropzone.dragover { + border-color: var(--primary); + background: #eef2ff; + transform: scale(1.01); +} + +[data-theme="dark"] .dropzone:hover, +[data-theme="dark"] .dropzone.dragover { + background: #1e1b4b; +} + +.dropzone.dragover { + box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.15); +} + +.dropzone-icon { + width: 72px; + height: 72px; + margin: 0 auto 1.25rem; + background: linear-gradient(135deg, #eef2ff, #e0e7ff); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + transition: transform var(--transition); +} + +[data-theme="dark"] .dropzone-icon { + background: linear-gradient(135deg, #312e81, #4338ca); +} + +.dropzone:hover .dropzone-icon { + transform: scale(1.1); +} + +.dropzone-title { + font-size: 1.1rem; + font-weight: 600; + margin-bottom: 0.5rem; +} + +.dropzone-hint { + font-size: 0.9rem; + color: var(--text-secondary); + max-width: 450px; + margin: 0 auto; +} + +/* ---------- Список файлов ---------- */ +.file-list { + margin-top: 1.5rem; +} + +.file-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 1rem; + background: var(--surface-alt); + border-radius: var(--radius-sm); + margin-bottom: 0.5rem; + border: 1px solid var(--border); + animation: slideIn 0.3s ease; +} + +.file-item.file-error { + border-color: var(--danger); + background: var(--danger-bg); +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(-8px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.file-icon { + width: 36px; + height: 36px; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.1rem; + flex-shrink: 0; +} + +.file-icon.vedomost { + background: #dbeafe; +} + +[data-theme="dark"] .file-icon.vedomost { + background: #1e3a5f; +} + +.file-icon.transaction { + background: #fef3c7; +} + +[data-theme="dark"] .file-icon.transaction { + background: #5c3d0e; +} + +.file-info { + flex: 1; + min-width: 0; +} + +.file-name { + font-size: 0.9rem; + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.file-type { + font-size: 0.8rem; + color: var(--text-muted); +} + +.file-remove { + width: 28px; + height: 28px; + border: none; + background: transparent; + border-radius: 6px; + cursor: pointer; + color: var(--text-muted); + font-size: 1.1rem; + display: flex; + align-items: center; + justify-content: center; + transition: all var(--transition); +} + +.file-remove:hover { + background: var(--danger-bg); + color: var(--danger); +} + +/* ---------- Кнопки ---------- */ +.actions { + display: flex; + gap: 0.75rem; + margin-top: 1.5rem; + flex-wrap: wrap; +} + +.btn { + padding: 0.75rem 1.75rem; + border: none; + border-radius: 10px; + font-size: 0.95rem; + font-weight: 600; + cursor: pointer; + transition: all var(--transition); + display: inline-flex; + align-items: center; + gap: 0.5rem; + white-space: nowrap; +} + +.btn:disabled { + opacity: 0.4; + cursor: not-allowed; + transform: none !important; +} + +.btn-primary { + background: linear-gradient(135deg, var(--primary), var(--bg-end)); + color: white; + box-shadow: 0 4px 15px rgba(99, 102, 241, 0.35); +} + +.btn-primary:hover:not(:disabled) { + transform: translateY(-2px); + box-shadow: 0 6px 25px rgba(99, 102, 241, 0.45); +} + +.btn-outline { + background: transparent; + color: var(--text-secondary); + border: 1.5px solid var(--border); +} + +.btn-outline:hover:not(:disabled) { + background: var(--surface-alt); + border-color: var(--text-muted); +} + +.btn-success { + background: linear-gradient(135deg, #10b981, #059669); + color: white; + box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3); +} + +.btn-success:hover:not(:disabled) { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4); +} + +.btn-export { + background: linear-gradient(135deg, #f59e0b, #d97706); + color: white; +} + +.btn-export:hover:not(:disabled) { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(245, 158, 11, 0.4); +} + +.btn-theme { + background: linear-gradient(135deg, #94a3b8, #64748b); + color: white; +} + +.btn-theme:hover:not(:disabled) { + transform: translateY(-2px); +} + +.btn-danger { + background: linear-gradient(135deg, #ef4444, #dc2626); + color: white; +} + +.btn-danger:hover:not(:disabled) { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(239, 68, 68, 0.4); +} + +/* ---------- Прогресс-бар ---------- */ +.progress-bar { + width: 100%; + height: 4px; + background: var(--border); + border-radius: 2px; + overflow: hidden; + margin-top: 1rem; + display: none; +} + +.progress-bar.active { + display: block; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--primary), var(--bg-end)); + border-radius: 2px; + width: 0%; +} + +/* ---------- Таблицы ---------- */ +.table-wrap { + overflow-x: auto; + border-radius: var(--radius-sm); + border: 1px solid var(--border); +} + +table { + width: 100%; + border-collapse: collapse; + font-size: 0.875rem; +} + +thead { + background: var(--surface-alt); +} + +th, +td { + padding: 0.75rem 1rem; + border-bottom: 1px solid var(--border); + text-align: left; +} + +th { + font-weight: 600; + color: var(--text-secondary); + white-space: nowrap; + user-select: none; +} + +th[data-key]::after { + content: ' ↕'; + opacity: 0.3; + font-size: 0.75rem; +} + +th.sort-asc::after { + content: ' ↑'; + opacity: 1; + color: var(--primary); +} + +th.sort-desc::after { + content: ' ↓'; + opacity: 1; + color: var(--primary); +} + +tbody tr:hover { + background: var(--surface-alt); +} + +tbody tr:last-child td { + border-bottom: none; +} + +/* ---------- Бейджи ---------- */ +.badge { + display: inline-flex; + align-items: center; + gap: 0.3rem; + padding: 0.2rem 0.65rem; + border-radius: 6px; + font-size: 0.8rem; + font-weight: 600; +} + +.badge-ok { + background: var(--success-bg); + color: var(--success-text); +} + +.badge-warn { + background: var(--warning-bg); + color: var(--warning-text); +} + +.badge-err { + background: var(--danger-bg); + color: var(--danger-text); +} + +/* ---------- Вкладки ---------- */ +.tabs-wrapper { + border-bottom: 2px solid var(--border); + margin-bottom: 1.5rem; + display: flex; + gap: 0.25rem; + overflow-x: auto; + scrollbar-width: none; +} + +.tabs-wrapper::-webkit-scrollbar { + display: none; +} + +.tab-btn { + padding: 0.75rem 1.25rem; + background: none; + border: none; + border-bottom: 2.5px solid transparent; + cursor: pointer; + font-size: 0.9rem; + font-weight: 600; + color: var(--text-muted); + white-space: nowrap; + transition: all var(--transition); + margin-bottom: -2px; +} + +.tab-btn:hover { + color: var(--primary); +} + +.tab-btn.active { + color: var(--primary); + border-bottom-color: var(--primary); +} + +.tab-btn .count { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 20px; + height: 20px; + background: var(--primary-light); + color: var(--primary-dark); + border-radius: 10px; + font-size: 0.75rem; + padding: 0 6px; + margin-left: 0.35rem; +} + +.tab-panel { + display: none; + animation: fadeUp 0.3s ease; +} + +.tab-panel.active { + display: block; +} + +@keyframes fadeUp { + from { + opacity: 0; + transform: translateY(8px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* ---------- Пустое состояние ---------- */ +.empty-state { + text-align: center; + padding: 3rem 1rem; +} + +.empty-state-icon { + font-size: 4rem; + margin-bottom: 1rem; + opacity: 0.3; +} + +.empty-state p { + color: var(--text-muted); +} + +/* ---------- Информационная карточка ---------- */ +.info-card { + background: var(--surface); + border-radius: var(--radius); + box-shadow: var(--shadow-md); + overflow: hidden; +} + +.info-head { + padding: 1.25rem 2rem; + border-bottom: 1px solid var(--border); + background: var(--surface-alt); + display: flex; + align-items: center; + gap: 0.75rem; +} + +.info-head h2 { + font-size: 1.25rem; + font-weight: 700; +} + +.info-grid { + padding: 1.5rem 2rem; + display: grid; + gap: 1.25rem; +} + +.info-block { + display: flex; + gap: 1rem; + padding: 1.25rem; + background: var(--surface-alt); + border-radius: 12px; + border: 1px solid var(--border); + transition: border-color var(--transition); +} + +.info-block:hover { + border-color: var(--primary-light); +} + +.info-block-icon { + width: 42px; + height: 42px; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.25rem; + flex-shrink: 0; +} + +.info-block-icon.blue { + background: #dbeafe; +} + +[data-theme="dark"] .info-block-icon.blue { + background: #1e3a5f; +} + +.info-block-icon.green { + background: #d1fae5; +} + +[data-theme="dark"] .info-block-icon.green { + background: #064e3b; +} + +.info-block-icon.amber { + background: #fef3c7; +} + +[data-theme="dark"] .info-block-icon.amber { + background: #78350f; +} + +.info-block-icon.purple { + background: #ede9fe; +} + +[data-theme="dark"] .info-block-icon.purple { + background: #2e1065; +} + +.info-block-icon.rose { + background: #ffe4e6; +} + +[data-theme="dark"] .info-block-icon.rose { + background: #4c0519; +} + +.info-block-title { + font-weight: 700; + font-size: 0.95rem; + margin-bottom: 0.35rem; +} + +.info-block-text { + font-size: 0.9rem; + color: var(--text-secondary); + line-height: 1.65; +} + +/* ---------- Сводка (выводы) ---------- */ +.summary-card { + padding: 1rem 0; +} + +.summary-card .info-block { + border-left: 4px solid var(--success); +} + +.summary-card .info-block.warn { + border-left-color: var(--warning); +} + +.summary-card .info-block.err { + border-left-color: var(--danger); +} + +/* ---------- Подвал ---------- */ +.footer { + text-align: center; + padding: 2rem 1rem; + color: rgba(255, 255, 255, 0.6); + font-size: 0.85rem; +} + +/* ---------- Адаптивность ---------- */ +@media (max-width: 768px) { + .container { + padding: 1rem 0.75rem 3rem; + } + + .hero { + padding: 1.5rem 0.5rem 2rem; + } + + .card-head { + padding: 1rem 1.25rem; + } + + .card-body { + padding: 1.25rem; + } + + .dropzone { + padding: 2rem 1rem; + } + + .actions { + flex-direction: column; + } + + .btn { + width: 100%; + justify-content: center; + } + + .info-grid { + padding: 1rem; + } + + .info-block { + flex-direction: column; + } + + th, + td { + padding: 0.5rem 0.75rem; + } +} + +/* ---------- Специфические утилиты ---------- */ +code { + font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; + font-size: 0.85em; + background: var(--surface-alt); + padding: 0.1em 0.3em; + border-radius: 4px; + border: 1px solid var(--border); +} + +.text-success { + color: var(--success); +} + +.text-danger { + color: var(--danger); +} + +.text-warning { + color: var(--warning); +} + +.text-muted { + color: var(--text-muted); +} + +.diff-positive { + color: var(--danger); + font-weight: 600; +} + +.diff-negative { + color: var(--success); + font-weight: 600; +} + +.diff-zero { + color: var(--text-muted); +} \ No newline at end of file