Files
futriix/internal/api/static/style.css

829 lines
15 KiB
CSS
Raw 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.
/*
* Copyright 2026 Safronov Grigorii
*
* Licensed under the CDDL, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* https://opensource.org/licenses/CDDL-1.0
*/
/* Файл: internal/api/static/style.css */
/* Стили для веб-интерфейса Futriis DB Dashboard */
:root {
--primary-color: #00bfff;
--primary-dark: #0099cc;
--secondary-color: #6c757d;
--success-color: #28a745;
--danger-color: #dc3545;
--warning-color: #ffc107;
--info-color: #17a2b8;
--bg-dark: #1a1a2e;
--bg-sidebar: #005385;
--bg-card: #0f3460;
--bg-hover: #1a1f3a;
--text-primary: #ffffff;
--text-secondary: #b8c6db;
--border-color: #2d3a5e;
--shadow-sm: 0 2px 4px rgba(0,0,0,0.1);
--shadow-md: 0 4px 8px rgba(0,0,0,0.15);
--shadow-lg: 0 8px 16px rgba(0,0,0,0.2);
--transition: all 0.3s ease;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg-dark);
color: var(--text-primary);
overflow: hidden;
}
/* Dashboard Container */
.dashboard-container {
display: flex;
height: 100vh;
width: 100%;
}
/* Sidebar - Вертикальное меню */
.sidebar {
width: 280px;
background: var(--bg-sidebar);
display: flex;
flex-direction: column;
transition: var(--transition);
box-shadow: var(--shadow-lg);
z-index: 100;
overflow-y: auto;
overflow-x: hidden;
}
.sidebar-header {
padding: 24px 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
display: flex;
align-items: center;
gap: 12px;
font-size: 1.5rem;
font-weight: 700;
}
.logo img {
width: 225px;
height: 107px;
object-fit: contain;
}
.logo span {
background: linear-gradient(135deg, var(--primary-color), #00ffcc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.menu-toggle {
display: none;
background: none;
border: none;
color: var(--text-primary);
font-size: 1.2rem;
cursor: pointer;
padding: 8px;
}
/* Navigation Menu */
.nav-menu {
flex: 1;
list-style: none;
padding: 20px 0;
}
.nav-item {
margin-bottom: 4px;
}
.nav-link {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 20px;
color: var(--text-secondary);
text-decoration: none;
transition: var(--transition);
border-radius: 8px;
margin: 0 8px;
}
.nav-link:hover {
background: var(--bg-hover);
color: var(--text-primary);
}
.nav-link.active {
background: var(--primary-color);
color: white;
}
.nav-link i {
width: 24px;
font-size: 1.1rem;
}
.nav-link span {
flex: 1;
}
/* Submenu */
.has-submenu > .nav-link {
position: relative;
}
.has-submenu > .nav-link .fa-chevron-down {
margin-left: auto;
transition: var(--transition);
}
.has-submenu.open > .nav-link .fa-chevron-down {
transform: rotate(180deg);
}
.submenu {
list-style: none;
padding-left: 56px;
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.has-submenu.open .submenu {
max-height: 500px;
}
.submenu li a {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
color: var(--text-secondary);
text-decoration: none;
font-size: 0.9rem;
transition: var(--transition);
border-radius: 6px;
margin: 2px 8px;
}
.submenu li a:hover {
background: var(--bg-hover);
color: var(--text-primary);
}
.submenu li a i {
width: 20px;
font-size: 0.9rem;
}
/* Sidebar Footer */
.sidebar-footer {
padding: 20px;
border-top: 1px solid var(--border-color);
}
.user-info {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
background: var(--bg-dark);
border-radius: 8px;
margin-bottom: 12px;
}
.user-info i {
font-size: 1.2rem;
color: var(--primary-color);
}
.logout-btn {
width: 100%;
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
background: var(--danger-color);
border: none;
color: white;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
transition: var(--transition);
}
.logout-btn:hover {
background: #c82333;
transform: translateY(-1px);
}
/* Main Content */
.main-content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.top-bar {
background: #1a1a2e;
padding: 16px 24px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border-color);
}
.top-bar h1 {
font-size: 1.5rem;
font-weight: 600;
}
.connection-status {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
background: var(--bg-dark);
border-radius: 24px;
font-size: 0.9rem;
font-weight: 500;
}
.connection-status i {
font-size: 0.8rem;
display: none;
}
.connection-status.online {
color: #00ff88;
background: rgba(0, 255, 136, 0.15);
text-shadow: 0 0 8px rgba(0, 255, 136, 0.5);
}
.connection-status.offline {
color: var(--danger-color);
background: rgba(220, 53, 69, 0.1);
}
.connection-status.online i {
display: none;
}
.connection-status.offline i {
display: none;
}
.connection-status::before {
content: "●";
margin-right: 8px;
font-size: 12px;
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
opacity: 0.6;
text-shadow: 0 0 2px currentColor;
}
50% {
opacity: 1;
text-shadow: 0 0 10px currentColor;
}
100% {
opacity: 0.6;
text-shadow: 0 0 2px currentColor;
}
}
.connection-status.online::before {
color: #00ff88;
}
.connection-status.offline::before {
color: var(--danger-color);
animation: none;
}
.content-area {
flex: 1;
overflow-y: auto;
padding: 24px;
}
/* Dashboard Cards */
.dashboard-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.stat-card {
background: var(--bg-card);
border-radius: 12px;
padding: 20px;
display: flex;
align-items: center;
gap: 16px;
transition: var(--transition);
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.stat-icon {
width: 60px;
height: 60px;
background: rgba(0, 191, 255, 0.1);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
}
.stat-icon i {
font-size: 2rem;
color: var(--primary-color);
}
.stat-info h3 {
font-size: 1.8rem;
font-weight: 700;
}
.stat-info p {
color: var(--text-secondary);
font-size: 0.85rem;
}
/* Tables */
.data-table {
width: 100%;
background: var(--bg-card);
border-radius: 12px;
overflow-x: auto;
}
.data-table table {
width: 100%;
border-collapse: collapse;
}
.data-table th,
.data-table td {
padding: 12px 16px;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
.data-table th {
background: var(--bg-sidebar);
font-weight: 600;
color: var(--primary-color);
}
.data-table tr:hover {
background: var(--bg-hover);
}
/* Forms */
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
}
.form-control {
width: 100%;
padding: 10px 12px;
background: #1a1a2e;
border: 1px solid var(--border-color);
border-radius: 8px;
color: var(--text-primary);
font-size: 0.95rem;
transition: var(--transition);
}
.form-control:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(0, 191, 255, 0.2);
background: #1a1a2e;
}
/* Подсветка полей ввода при наведении мыши - только рамка */
.form-control:hover {
border-color: var(--primary-color);
background: #1a1a2e;
}
textarea.form-control {
min-height: 120px;
font-family: monospace;
resize: vertical;
}
/* Buttons - общие стили для всех кнопок */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 20px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 0.95rem;
font-weight: 500;
transition: var(--transition);
text-decoration: none;
width: auto;
min-width: 80px;
}
/* Стили для кнопки "Войти" (primary) */
.btn-primary {
background: #1a1a2e;
color: white;
}
.btn-primary:hover {
background: #2a2a4e;
transform: translateY(-1px);
}
/* Стили для кнопки "Отмена" (secondary) - полностью идентичны кнопке "Войти" */
.btn-secondary {
background: #1a1a2e;
color: white;
}
.btn-secondary:hover {
background: #2a2a4e;
transform: translateY(-1px);
}
.btn-danger {
background: var(--danger-color);
color: white;
}
.btn-danger:hover {
background: #c82333;
}
.btn-sm {
padding: 6px 12px;
font-size: 0.85rem;
}
/* Modal */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
z-index: 1000;
align-items: center;
justify-content: center;
}
.modal.show {
display: flex;
}
.modal-content {
background: #005385;
border-radius: 16px;
width: 90%;
max-width: 500px;
max-height: 80vh;
display: flex;
flex-direction: column;
animation: modalSlideIn 0.3s ease;
position: relative;
}
@keyframes modalSlideIn {
from {
transform: translateY(-50px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.modal-header {
padding: 20px 24px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
.modal-header h2 {
font-size: 1.5rem;
font-weight: 600;
color: var(--text-primary);
margin: 0;
}
.modal-close {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--text-secondary);
padding: 0;
/* width: 32px; */
/* height: 32px; */
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
transition: var(--transition);
}
.modal-close:hover {
background: rgba(255, 255, 255, 0.1);
color: var(--text-primary);
}
.modal-body {
padding: 24px;
overflow-y: auto;
flex: 1;
}
.modal-footer {
padding: 16px 24px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
justify-content: flex-end;
gap: 12px;
flex-direction: row-reverse;
}
/* Стили для кнопок в модальном окне - обе кнопки имеют одинаковый фон на всю площадь */
.modal-footer .btn {
font-size: 0.9rem;
padding: 10px 24px;
border-radius: 8px;
width: auto;
min-width: 100px;
}
/* Кнопка "Войти" в модальном окне */
.modal-footer .btn-primary {
background: #1a1a2e;
color: white;
border: none;
}
.modal-footer .btn-primary:hover {
background: #2a2a4e;
transform: translateY(-1px);
}
/* Кнопка "Отмена" в модальном окне - полностью идентична кнопке "Войти" */
.modal-footer .btn-secondary {
background: #1a1a2e;
color: white;
border: none;
}
.modal-footer .btn-secondary:hover {
background: #2a2a4e;
transform: translateY(-1px);
}
/* Notifications */
.notification-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 1100;
}
.notification {
background: var(--bg-card);
border-radius: 8px;
padding: 12px 20px;
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 12px;
box-shadow: var(--shadow-lg);
animation: slideInRight 0.3s ease;
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.notification.success {
border-left: 4px solid var(--success-color);
}
.notification.error {
border-left: 4px solid var(--danger-color);
}
.notification.warning {
border-left: 4px solid var(--warning-color);
}
.notification.info {
border-left: 4px solid var(--info-color);
}
/* Loading Spinner */
.loading-spinner {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 200px;
}
.loading-spinner i {
font-size: 3rem;
color: var(--primary-color);
}
.loading-spinner p {
margin-top: 16px;
color: var(--text-secondary);
}
/* Tabs */
.tabs {
display: flex;
gap: 8px;
margin-bottom: 20px;
border-bottom: 1px solid var(--border-color);
padding-bottom: 8px;
}
.tab-btn {
padding: 8px 16px;
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
border-radius: 6px;
transition: var(--transition);
}
.tab-btn.active {
background: var(--primary-color);
color: white;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
/* Responsive Design */
@media (max-width: 768px) {
.sidebar {
position: fixed;
left: -280px;
height: 100%;
transition: left 0.3s ease;
}
.sidebar.open {
left: 0;
}
.menu-toggle {
display: block;
}
.main-content {
margin-left: 0;
}
.dashboard-stats {
grid-template-columns: 1fr;
}
.data-table {
font-size: 0.85rem;
}
.data-table th,
.data-table td {
padding: 8px 12px;
}
.modal-content {
width: 95%;
margin: 20px;
}
.logo img {
width: 180px;
height: 86px;
}
}
@media (max-width: 480px) {
.top-bar h1 {
font-size: 1.2rem;
}
.stat-card {
padding: 16px;
}
.stat-icon {
width: 50px;
height: 50px;
}
.stat-info h3 {
font-size: 1.4rem;
}
.logo img {
width: 150px;
height: 71px;
}
.connection-status {
padding: 4px 10px;
font-size: 0.75rem;
}
.connection-status::before {
font-size: 8px;
margin-right: 4px;
}
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: var(--bg-dark);
}
::-webkit-scrollbar-thumb {
background: var(--border-color);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--primary-color);
}