Add comprehensive backend features and mobile UI improvements

Backend:
- Add 2FA authentication with TOTP support
- Add API keys management system
- Add audit logging for security events
- Add file upload/management system
- Add notifications system with preferences
- Add session management
- Add webhooks integration
- Add analytics endpoints
- Add export functionality
- Add password policy enforcement
- Add new database migrations for core tables

Frontend:
- Add module position system (top/bottom sidebar sections)
- Add search and notifications module configuration tabs
- Add mobile logo replacing hamburger menu
- Center page title absolutely when no tabs present
- Align sidebar footer toggles with navigation items
- Add lighter icon color in dark theme for mobile
- Add API keys management page
- Add notifications page with context
- Add admin analytics and audit logs pages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-17 22:27:32 +01:00
parent f698aa4d51
commit 8c4a555b88
76 changed files with 9751 additions and 323 deletions

View File

@@ -0,0 +1,154 @@
.api-keys-root .page-content {
max-width: var(--container-lg);
}
/* Section Layout - matches theme-section spacing */
.api-keys-section {
margin-bottom: 3rem;
}
.api-keys-section:last-child {
margin-bottom: 0;
}
.api-keys-desc {
margin: 0.25rem 0 1rem;
color: var(--color-text-secondary);
font-size: 0.9rem;
line-height: 1.5;
}
.api-keys-create-row {
display: flex;
gap: 0.75rem;
align-items: center;
flex-wrap: wrap;
}
.api-keys-input {
flex: 1;
min-width: 240px;
height: var(--height-input);
padding: 0 0.875rem;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-md);
background: var(--color-bg-elevated);
color: var(--color-text-primary);
font-size: var(--input-font-size);
transition: border-color var(--transition-base), box-shadow var(--transition-base), background-color var(--transition-base);
}
.api-keys-input:focus {
outline: none;
border-color: rgba(var(--color-accent-rgb), 0.45);
box-shadow: var(--shadow-ring);
}
.api-keys-created {
margin-top: 1rem;
padding: 0.9rem;
border: 1px solid rgba(var(--color-accent-rgb), 0.25);
border-radius: var(--radius-lg);
background: rgba(var(--color-accent-rgb), 0.06);
}
.api-keys-created-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
margin-bottom: 0.75rem;
}
.api-keys-created-key {
display: block;
padding: 0.75rem;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-md);
background: var(--color-bg-elevated);
overflow-x: auto;
font-family: var(--font-mono);
font-size: 0.9rem;
line-height: 1.4;
}
.api-keys-empty {
padding: 1.25rem;
border: 1px dashed var(--color-card-outline);
border-radius: var(--radius-lg);
color: var(--color-text-secondary);
text-align: center;
font-size: 0.9rem;
margin-top: 1rem;
}
.api-keys-table-card {
margin-top: 1rem;
background: var(--color-bg-card);
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm);
overflow: hidden;
}
@supports (color: color-mix(in srgb, black, transparent)) {
.api-keys-table-card {
background: color-mix(in srgb, var(--color-bg-card) 88%, transparent);
backdrop-filter: blur(14px) saturate(1.1);
}
}
.api-keys-table {
width: 100%;
border-collapse: collapse;
}
.api-keys-table th,
.api-keys-table td {
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--color-card-outline);
text-align: left;
vertical-align: middle;
font-size: 0.9rem;
}
.api-keys-table th {
color: var(--color-text-secondary);
font-size: 0.82rem;
font-weight: 700;
letter-spacing: 0.02em;
text-transform: uppercase;
background: var(--color-bg-elevated);
}
.api-keys-table tbody tr:hover {
background: rgba(var(--color-accent-rgb), 0.05);
}
.api-keys-table tr:last-child td {
border-bottom: none;
}
.api-keys-actions {
display: inline-flex;
gap: 0.75rem;
align-items: center;
}
.api-keys-muted {
color: var(--color-text-secondary);
font-size: 0.85rem;
}
/* ========== DARK THEME + AUTO ACCENT OVERRIDES ========== */
/* Input focus */
[data-theme='dark'][data-accent='auto'] .api-keys-input:focus {
border-color: rgba(229, 231, 235, 0.45);
}
/* Created key box */
[data-theme='dark'][data-accent='auto'] .api-keys-created {
border-color: rgba(229, 231, 235, 0.25);
background: rgba(229, 231, 235, 0.06);
}

View File

@@ -0,0 +1,196 @@
.admin-analytics-root .page-content {
max-width: 1100px;
}
.analytics-cards {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: var(--section-gap-sm);
margin-bottom: var(--section-gap);
}
.analytics-card {
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
padding: var(--space-5);
background: var(--color-bg-card);
box-shadow: var(--shadow-sm);
transition: box-shadow var(--transition-base), border-color var(--transition-base);
}
@supports (color: color-mix(in srgb, black, transparent)) {
.analytics-card {
background: color-mix(in srgb, var(--color-bg-card) 88%, transparent);
backdrop-filter: blur(14px) saturate(1.1);
}
}
.analytics-card:hover {
box-shadow: var(--shadow-md);
border-color: rgba(var(--color-accent-rgb), 0.22);
}
.analytics-card-title {
color: var(--color-text-secondary);
font-size: var(--badge-font-size);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.analytics-card-value {
font-size: var(--text-2xl);
font-weight: var(--weight-bold);
color: var(--color-text-primary);
margin-top: var(--space-1);
font-variant-numeric: tabular-nums;
line-height: var(--leading-tight);
}
.analytics-card-sub {
margin-top: var(--space-2);
color: var(--color-text-secondary);
font-size: var(--text-base);
}
.analytics-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--section-gap-sm);
}
.analytics-panel {
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
padding: var(--space-5);
background: var(--color-bg-card);
box-shadow: var(--shadow-sm);
transition: box-shadow var(--transition-base), border-color var(--transition-base);
}
@supports (color: color-mix(in srgb, black, transparent)) {
.analytics-panel {
background: color-mix(in srgb, var(--color-bg-card) 88%, transparent);
backdrop-filter: blur(14px) saturate(1.1);
}
}
.analytics-panel:hover {
box-shadow: var(--shadow-md);
border-color: rgba(var(--color-accent-rgb), 0.18);
}
.analytics-panel .section-title {
margin: 0 0 var(--space-3) 0;
}
.mini-chart {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.mini-chart-row {
display: grid;
grid-template-columns: 95px 1fr 64px;
gap: 0.75rem;
align-items: center;
}
.mini-chart-label {
color: var(--color-text-secondary);
font-size: 0.82rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.mini-chart-bars {
display: flex;
flex-direction: column;
gap: 4px;
}
.mini-bar {
height: 10px;
border-radius: 999px;
}
.mini-bar.bar-accent {
background: rgba(var(--color-accent-rgb), 0.75);
}
.mini-bar.bar-muted {
background: rgba(156, 163, 175, 0.6);
}
.mini-chart-values {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
color: var(--color-text-secondary);
font-size: 0.82rem;
font-variant-numeric: tabular-nums;
}
.mini-chart-legend {
display: flex;
gap: 1rem;
margin-top: 0.75rem;
color: var(--color-text-secondary);
font-size: 0.85rem;
}
.legend-item {
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.legend-dot {
width: 10px;
height: 10px;
border-radius: 999px;
}
.legend-dot.accent {
background: rgba(var(--color-accent-rgb), 0.75);
}
.legend-dot.muted {
background: rgba(156, 163, 175, 0.6);
}
.analytics-footnote {
margin-top: 1rem;
color: var(--color-text-secondary);
font-size: 0.85rem;
}
@media (max-width: 1000px) {
.analytics-cards {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.analytics-grid {
grid-template-columns: 1fr;
}
}
@media (max-width: 520px) {
.mini-chart-row {
grid-template-columns: 80px 1fr 56px;
}
}
/* ========== DARK THEME + AUTO ACCENT OVERRIDES ========== */
/* Mini bar accent color */
[data-theme='dark'][data-accent='auto'] .mini-bar.bar-accent {
background: rgba(229, 231, 235, 0.75);
}
/* Legend dot accent */
[data-theme='dark'][data-accent='auto'] .legend-dot.accent {
background: rgba(229, 231, 235, 0.75);
}

View File

@@ -0,0 +1,149 @@
.admin-audit-root .page-content {
max-width: 1200px;
}
.audit-filters {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
align-items: center;
margin-bottom: var(--section-gap);
}
.audit-reset-btn {
margin-left: auto;
height: var(--height-input);
padding: 0 1rem;
background: var(--color-bg-card);
color: var(--color-text-primary);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
font-size: 0.85rem;
font-weight: 500;
cursor: pointer;
transition: background-color var(--transition-base), border-color var(--transition-base);
}
.audit-reset-btn:hover:not(:disabled) {
background: var(--color-bg-hover);
border-color: var(--color-text-secondary);
}
.audit-reset-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.audit-input {
height: var(--height-input);
padding: 0 0.875rem;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-md);
background: var(--color-bg-elevated);
color: var(--color-text-primary);
font-size: 0.85rem;
min-width: 160px;
transition: border-color var(--transition-base), box-shadow var(--transition-base), background-color var(--transition-base);
}
.audit-input:focus {
outline: none;
border-color: rgba(var(--color-accent-rgb), 0.45);
box-shadow: var(--shadow-ring);
}
.audit-table-card {
background: var(--color-bg-card);
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm);
overflow: hidden;
}
@supports (color: color-mix(in srgb, black, transparent)) {
.audit-table-card {
background: color-mix(in srgb, var(--color-bg-card) 88%, transparent);
backdrop-filter: blur(14px) saturate(1.1);
}
}
.audit-table {
width: 100%;
border-collapse: collapse;
}
.audit-table th,
.audit-table td {
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--color-card-outline);
text-align: left;
vertical-align: middle;
font-size: 0.9rem;
}
.audit-table th {
color: var(--color-text-secondary);
font-size: 0.82rem;
font-weight: 700;
letter-spacing: 0.02em;
text-transform: uppercase;
background: var(--color-bg-elevated);
}
.audit-table tbody tr:hover {
background: rgba(var(--color-accent-rgb), 0.05);
}
.audit-table tr:last-child td {
border-bottom: none;
}
.audit-table .mono {
font-size: 0.85rem;
font-variant-numeric: tabular-nums;
color: var(--color-text-secondary);
}
.audit-empty {
padding: 2rem 1.25rem;
border: 1px dashed var(--color-card-outline);
border-radius: var(--radius-lg);
color: var(--color-text-secondary);
text-align: center;
font-size: 0.9rem;
}
.audit-pagination {
display: flex;
align-items: center;
justify-content: center;
gap: 1.25rem;
margin-top: 1.25rem;
padding-top: 1rem;
border-top: 1px solid var(--color-card-outline);
}
.audit-page-indicator {
color: var(--color-text-secondary);
font-size: 0.85rem;
font-weight: 500;
}
/* ========== DARK THEME OVERRIDES ========== */
/* Reset button - light in dark mode */
[data-theme='dark'] .audit-reset-btn {
background: #e2e8f0;
color: #1e293b;
border-color: #cbd5e1;
}
[data-theme='dark'] .audit-reset-btn:hover:not(:disabled) {
background: #f1f5f9;
border-color: #94a3b8;
}
/* Input focus - auto accent */
[data-theme='dark'][data-accent='auto'] .audit-input:focus {
border-color: rgba(229, 231, 235, 0.45);
}

View File

@@ -52,6 +52,18 @@
border: 1px solid rgba(var(--color-accent-rgb), 0.2);
}
.badge-error {
background: rgba(239, 68, 68, 0.1);
color: #dc2626;
border: 1px solid rgba(239, 68, 68, 0.2);
}
.badge-warning {
background: rgba(245, 158, 11, 0.1);
color: #d97706;
border: 1px solid rgba(245, 158, 11, 0.2);
}
/* Toolbar - single row with search left, badges+button right */
.admin-panel-root .users-toolbar,
.users-root .users-toolbar {
@@ -101,6 +113,123 @@
font-size: var(--icon-md);
}
/* Link-style Button */
.btn-link {
background: none;
border: none;
color: var(--color-accent);
cursor: pointer;
text-decoration: none;
font-size: 0.9rem;
font-weight: 600;
padding: 0.25rem 0.5rem;
border-radius: var(--radius-sm);
transition: all 0.2s ease;
}
.btn-link:hover {
color: var(--color-accent-hover);
background: rgba(var(--color-accent-rgb), 0.08);
}
.btn-link.danger {
color: var(--color-error);
}
.btn-link.danger:hover {
color: #b91c1c;
background: rgba(239, 68, 68, 0.08);
}
.btn-link:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Danger Button */
.btn-danger {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: var(--btn-padding-md);
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
color: white;
border: none;
border-radius: var(--radius-md);
font-weight: 600;
font-size: var(--btn-font-size);
cursor: pointer;
transition: transform var(--transition-base), box-shadow var(--transition-base), filter var(--transition-base);
box-shadow: var(--shadow-md);
}
.btn-danger:hover {
filter: brightness(1.05);
transform: translateY(-1px);
box-shadow: var(--shadow-lg);
}
.btn-danger:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
/* Ghost Button */
.btn-ghost {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: var(--btn-padding-md);
background: transparent;
color: var(--color-text-primary);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
font-weight: 500;
font-size: var(--btn-font-size);
cursor: pointer;
transition: all 0.2s ease;
}
.btn-ghost:hover {
background: var(--color-bg-elevated);
border-color: var(--color-accent);
}
.btn-ghost.danger {
color: var(--color-error);
border-color: rgba(239, 68, 68, 0.3);
}
.btn-ghost.danger:hover {
background: rgba(239, 68, 68, 0.08);
border-color: var(--color-error);
}
.btn-ghost:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Error Message */
.error-message {
background: rgba(239, 68, 68, 0.1);
color: var(--color-error);
padding: 0.75rem 1rem;
border-radius: var(--radius-md);
margin-bottom: 1rem;
border: 1px solid rgba(239, 68, 68, 0.25);
font-weight: 500;
}
/* Loading State */
.loading {
padding: 2rem 1.25rem;
color: var(--color-text-secondary);
text-align: center;
font-size: 0.95rem;
}
/* Small button variant */
.btn-sm {
padding: var(--btn-padding-sm) !important;
@@ -389,21 +518,26 @@
.admin-panel-root .users-table td,
.users-root .users-table th,
.users-root .users-table td {
padding: var(--table-cell-padding);
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--color-card-outline);
text-align: left;
vertical-align: middle;
font-size: 0.9rem;
}
.admin-panel-root .users-table tbody tr:not(:last-child),
.users-root .users-table tbody tr:not(:last-child) {
border-bottom: 1px solid var(--color-border);
.admin-panel-root .users-table tr:last-child td,
.users-root .users-table tr:last-child td {
border-bottom: none;
}
.admin-panel-root .users-table th,
.users-root .users-table th {
font-weight: 700;
font-size: 0.82rem;
color: var(--color-text-secondary);
background: var(--color-bg-elevated);
text-transform: uppercase;
letter-spacing: 0.02em;
white-space: nowrap;
}
@@ -436,7 +570,7 @@
.admin-panel-root .users-table tbody tr:hover,
.users-root .users-table tbody tr:hover {
background: var(--color-bg-elevated);
background: rgba(var(--color-accent-rgb), 0.05);
}
.admin-panel-root .user-cell,
@@ -1112,16 +1246,22 @@
border-collapse: collapse;
}
.modern-table th {
padding: 1rem 1.5rem;
.modern-table th,
.modern-table td {
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--color-card-outline);
text-align: left;
font-weight: 600;
font-size: 0.85rem;
vertical-align: middle;
font-size: 0.9rem;
}
.modern-table th {
font-weight: 700;
font-size: 0.82rem;
text-transform: uppercase;
letter-spacing: 0.5px;
letter-spacing: 0.02em;
color: var(--color-text-secondary);
background: var(--color-bg-elevated);
border-bottom: 2px solid var(--color-border);
}
.modern-table th.actions-col {
@@ -1129,18 +1269,12 @@
text-align: center;
}
.modern-table td {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid var(--color-border);
vertical-align: middle;
}
.modern-table tbody tr:last-child td {
border-bottom: none;
}
.modern-table tbody tr:hover {
background: var(--color-bg-elevated);
background: rgba(var(--color-accent-rgb), 0.05);
}
.modern-table .user-info {
@@ -2134,43 +2268,12 @@
}
}
/* Feature Header - Clean style for feature toggles */
.feature-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 2rem;
margin-bottom: 2rem;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--color-border);
}
.feature-header-info {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.feature-header-info h2 {
margin: 0;
font-size: 1.25rem;
font-weight: 600;
color: var(--color-text-primary);
}
.feature-header-info p {
margin: 0;
color: var(--color-text-secondary);
font-size: 0.95rem;
line-height: 1.5;
}
.feature-header-actions {
/* Feature Config Options */
.feature-config-options {
display: flex;
align-items: center;
gap: 1rem;
padding-top: 0.25rem;
/* Align with text top */
flex-wrap: wrap;
}
/* Status badge in header */
@@ -2188,9 +2291,15 @@
}
.feature-status-badge.active {
background: rgba(var(--color-accent-rgb), 0.1);
color: var(--color-accent);
border-color: rgba(var(--color-accent-rgb), 0.2);
background: rgba(5, 150, 105, 0.15);
color: #047857;
border-color: rgba(5, 150, 105, 0.3);
}
[data-theme='dark'] .feature-status-badge.active {
background: rgba(16, 185, 129, 0.2);
color: #34d399;
border-color: rgba(16, 185, 129, 0.35);
}
.feature-status-badge::before {
@@ -2227,38 +2336,10 @@
background: var(--color-bg-elevated);
}
/* Feature Header Mobile - Stack description above toggles */
/* Mobile styles */
@media (max-width: 768px) {
.feature-header {
flex-direction: column;
align-items: stretch;
gap: 1.25rem;
padding-bottom: 1.25rem;
margin-bottom: 1.5rem;
}
.feature-header-info {
width: 100%;
text-align: center;
}
.feature-header-info h2 {
font-size: 1.1rem;
}
.feature-header-info p {
font-size: 0.9rem;
}
.feature-header-actions {
width: 100%;
justify-content: center;
border-top: 1px solid var(--color-border);
padding-top: 1rem;
}
.feature-header-actions .toggle-group {
justify-content: center;
.feature-config-options {
justify-content: flex-start;
}
/* Admin Tab Tooltip - Mobile Only */
@@ -2342,11 +2423,9 @@
color: #e5e7eb;
}
/* Feature status badge active */
[data-theme='dark'][data-accent='auto'] .feature-status-badge.active {
background: rgba(229, 231, 235, 0.1);
color: #e5e7eb;
border-color: rgba(229, 231, 235, 0.2);
/* Ghost button hover */
[data-theme='dark'][data-accent='auto'] .btn-ghost:hover {
border-color: #e5e7eb;
}
/* Focus states */
@@ -2379,6 +2458,22 @@
background: #111827;
}
/* Link button with auto accent */
[data-theme='dark'][data-accent='auto'] .btn-link {
color: #e5e7eb;
}
[data-theme='dark'][data-accent='auto'] .btn-link:hover {
color: #f3f4f6;
background: rgba(229, 231, 235, 0.12);
}
/* Order card icon with auto accent */
[data-theme='dark'][data-accent='auto'] .order-card-preview .material-symbols-outlined {
color: #e5e7eb;
}
/* ===========================================
ORDER CARDS - Feature Ordering (Theme Editor Style)
=========================================== */
@@ -2436,9 +2531,8 @@
border: 1px solid var(--color-border);
}
.order-card-number {
font-size: 1.1rem;
font-weight: 700;
.order-card-preview .material-symbols-outlined {
font-size: 20px;
color: var(--color-accent);
}
@@ -2462,23 +2556,6 @@
color: var(--color-text-secondary);
}
/* Order Card Icon */
.order-card-icon {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
background: rgba(var(--color-accent-rgb), 0.1);
border-radius: var(--radius-md);
}
.order-card-icon .material-symbols-outlined {
font-size: 20px;
color: var(--color-accent);
}
/* Order Card Handle */
.order-card-handle {
flex-shrink: 0;
@@ -2503,6 +2580,48 @@
color: var(--color-text-secondary);
}
/* Order Card Position Button */
.order-card-position-btn {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
padding: 0;
background: var(--color-bg-elevated);
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-md);
cursor: pointer;
transition: all 0.2s ease;
}
.order-card-position-btn:hover {
background: rgba(var(--color-accent-rgb), 0.1);
border-color: rgba(var(--color-accent-rgb), 0.3);
}
.order-card-position-btn .material-symbols-outlined {
font-size: 18px;
color: var(--color-text-secondary);
transition: color 0.2s ease;
}
.order-card-position-btn:hover .material-symbols-outlined {
color: var(--color-accent);
}
/* Order Empty State */
.order-empty {
padding: 1.5rem;
text-align: center;
color: var(--color-text-muted);
font-size: 0.9rem;
border: 1px dashed var(--color-card-outline);
border-radius: var(--radius-lg);
background: rgba(var(--color-accent-rgb), 0.02);
}
/* Order Actions */
.order-actions {
margin-top: 1.5rem;

View File

@@ -160,7 +160,7 @@
/* Standard Section Title */
.section-title {
margin: 0;
margin: 0 0 1rem 0;
font-size: 0.8rem;
font-weight: 600;
text-transform: uppercase;
@@ -203,7 +203,7 @@
}
.mobile-menu-btn:hover {
background: rgba(var(--color-accent-rgb), 0.1);
background-color: rgba(var(--color-accent-rgb), 0.1);
color: var(--color-accent);
}
@@ -211,6 +211,7 @@
font-size: var(--icon-lg);
}
/* ========== ACTION BUTTONS IN SLIDER ========== */
/* Action buttons that appear in the slider (like Add User) */
@@ -286,9 +287,30 @@
margin-left: 0;
}
/* Show mobile menu button */
/* Show mobile menu button with logo */
.mobile-menu-btn {
display: flex;
position: absolute;
left: 4px;
top: 50%;
transform: translateY(-50%);
z-index: 1;
background-image: url('/logo_black.svg');
background-size: 28px 28px;
background-repeat: no-repeat;
background-position: center;
}
.mobile-menu-btn .material-symbols-outlined {
display: none;
}
[data-theme='dark'] .mobile-menu-btn {
background-image: url('/logo_white.svg');
}
.mobile-menu-btn:hover {
background-color: transparent;
}
.page-tabs-container,
@@ -302,6 +324,7 @@
flex-wrap: wrap;
justify-content: flex-start;
gap: 8px;
position: relative;
}
.page-title-section,
@@ -309,6 +332,7 @@
flex: 1;
justify-content: flex-start;
padding: 0.5rem 0.75rem;
padding-left: 48px;
font-size: 1rem;
}
@@ -323,6 +347,35 @@
display: none;
}
/* Hide title section when tabs are present on mobile */
.page-tabs-slider:has(.page-tab-btn) .page-title-section,
.admin-tabs-slider:has(.admin-tab-btn) .admin-title-section {
display: none;
}
/* Center title section absolutely when no tabs are present on mobile */
.page-tabs-slider:not(:has(.page-tab-btn)),
.admin-tabs-slider:not(:has(.admin-tab-btn)) {
justify-content: center;
min-height: 48px;
}
.page-tabs-slider:not(:has(.page-tab-btn)) .page-title-section,
.admin-tabs-slider:not(:has(.admin-tab-btn)) .admin-title-section {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 0.5rem 0.75rem;
flex: none;
}
/* Lighter icon color in dark theme when only title is shown */
.page-tabs-slider:not(:has(.page-tab-btn)) .page-title-section .material-symbols-outlined,
.admin-tabs-slider:not(:has(.admin-tab-btn)) .admin-title-section .material-symbols-outlined {
color: var(--color-text-secondary);
}
/* Tabs on second row - full width */
.page-tab-btn,
.admin-tab-btn {

View File

@@ -198,7 +198,7 @@
transform: translateY(-1px);
}
.error-message {
.login-container .error-message {
background: rgba(245, 101, 101, 0.1);
color: var(--color-error);
padding: 0.75rem;

View File

@@ -0,0 +1,202 @@
.notifications-root .page-content {
max-width: 900px;
}
.notifications-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--toolbar-gap);
margin-bottom: var(--section-gap);
flex-wrap: wrap;
}
.notifications-toggle {
display: inline-flex;
align-items: center;
gap: var(--element-gap-lg);
}
.notifications-toggle-label {
color: var(--color-text-secondary);
font-size: 0.85rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.notifications-actions {
display: inline-flex;
align-items: center;
gap: var(--element-gap-lg);
}
.notifications-empty {
padding: 2rem 1.25rem;
border: 1px dashed var(--color-card-outline);
border-radius: var(--radius-lg);
color: var(--color-text-secondary);
text-align: center;
font-size: 0.9rem;
background: var(--color-bg-card);
box-shadow: var(--shadow-sm);
}
@supports (color: color-mix(in srgb, black, transparent)) {
.notifications-empty {
background: color-mix(in srgb, var(--color-bg-card) 88%, transparent);
backdrop-filter: blur(14px) saturate(1.1);
}
}
.notifications-list {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.notification-item {
display: flex;
gap: 1rem;
align-items: flex-start;
justify-content: space-between;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
padding: var(--space-5);
background: var(--color-bg-card);
box-shadow: var(--shadow-sm);
transition: box-shadow var(--transition-base), border-color var(--transition-base);
}
@supports (color: color-mix(in srgb, black, transparent)) {
.notification-item {
background: color-mix(in srgb, var(--color-bg-card) 88%, transparent);
backdrop-filter: blur(14px) saturate(1.1);
}
}
.notification-item:hover {
box-shadow: var(--shadow-md);
border-color: rgba(var(--color-accent-rgb), 0.18);
}
.notification-item.unread {
border-color: rgba(var(--color-accent-rgb), 0.35);
box-shadow: var(--shadow-sm), 0 0 0 3px rgba(var(--color-accent-rgb), 0.08);
}
.notification-main {
min-width: 0;
flex: 1;
}
.notification-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.notification-title {
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-weight: 600;
font-size: 0.9rem;
color: var(--color-text-primary);
min-width: 0;
}
.notification-title span:last-child {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.notification-date {
color: var(--color-text-secondary);
font-size: 0.85rem;
flex: 0 0 auto;
}
.notification-message {
margin-top: 0.5rem;
color: var(--color-text-secondary);
font-size: 0.9rem;
white-space: pre-wrap;
line-height: 1.5;
}
.notification-actions {
display: inline-flex;
flex-direction: column;
gap: 0.5rem;
align-items: flex-end;
flex: 0 0 auto;
}
.notification-type {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.15rem 0.5rem;
font-size: 0.75rem;
font-weight: 700;
border-radius: 999px;
border: 1px solid var(--color-card-outline);
background: var(--color-bg-elevated);
color: var(--color-text-secondary);
text-transform: uppercase;
}
.notification-type.type-success {
background: rgba(34, 197, 94, 0.1);
border-color: rgba(34, 197, 94, 0.25);
color: #16a34a;
}
.notification-type.type-warning {
background: rgba(245, 158, 11, 0.12);
border-color: rgba(245, 158, 11, 0.3);
color: #b45309;
}
.notification-type.type-error {
background: rgba(239, 68, 68, 0.1);
border-color: rgba(239, 68, 68, 0.25);
color: #dc2626;
}
.notification-type.type-system {
background: rgba(var(--color-accent-rgb), 0.1);
border-color: rgba(var(--color-accent-rgb), 0.2);
color: var(--color-accent);
}
@media (max-width: 768px) {
.notification-item {
flex-direction: column;
gap: 0.75rem;
}
.notification-actions {
flex-direction: row;
width: 100%;
justify-content: flex-end;
}
}
/* ========== DARK THEME + AUTO ACCENT OVERRIDES ========== */
/* Unread notification border */
[data-theme='dark'][data-accent='auto'] .notification-item.unread {
border-color: rgba(229, 231, 235, 0.35);
box-shadow: var(--shadow-sm), 0 0 0 3px rgba(229, 231, 235, 0.08);
}
/* System type badge */
[data-theme='dark'][data-accent='auto'] .notification-type.type-system {
background: rgba(229, 231, 235, 0.1);
border-color: rgba(229, 231, 235, 0.2);
color: #e5e7eb;
}

View File

@@ -17,27 +17,22 @@
max-width: 800px;
}
/* Settings Sections */
.settings-section-modern {
background: var(--color-bg-card);
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
padding: 2rem;
box-shadow: var(--shadow-sm);
margin-bottom: 1.5rem;
/* Settings Sections - no card, just spacing */
.settings-section {
margin-bottom: 3rem;
}
@supports (color: color-mix(in srgb, black, transparent)) {
.settings-section-modern {
background: color-mix(in srgb, var(--color-bg-card) 88%, transparent);
backdrop-filter: blur(14px) saturate(1.1);
}
}
.settings-section-modern:last-child {
.settings-section:last-child {
margin-bottom: 0;
}
.settings-section-desc {
margin: 0 0 1rem;
color: var(--color-text-secondary);
font-size: 0.9rem;
line-height: 1.5;
}
/* Section title uses standard .section-title from Layout.css */
.setting-item-modern {
@@ -45,17 +40,14 @@
justify-content: space-between;
align-items: center;
gap: 2rem;
padding: 1.5rem 0;
border-bottom: 1px solid var(--color-card-outline);
padding: 1rem;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
background: var(--color-bg-card);
}
.setting-item-modern:last-child {
border-bottom: none;
padding-bottom: 0;
}
.setting-item-modern:first-child {
padding-top: 0;
.setting-item-modern + .setting-item-modern {
margin-top: 0.75rem;
}
.setting-info-modern {
@@ -181,3 +173,213 @@
gap: 1rem;
}
}
/* Security section helpers */
.settings-security-details {
margin-top: 1.25rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
.settings-security-details > .btn-primary {
align-self: flex-start;
justify-content: center;
min-width: 140px;
}
.settings-backup-codes-section {
margin-top: 1rem;
padding: 1rem;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
background: var(--color-bg-card);
}
.settings-backup-codes-section h4 {
margin: 0 0 0.25rem;
}
.settings-backup-codes-section p {
margin: 0 0 0.75rem;
color: var(--color-text-secondary);
font-size: 0.9rem;
}
.settings-twofa-setup {
display: flex;
gap: 1.25rem;
align-items: flex-start;
}
.settings-twofa-qr {
flex: 0 0 auto;
padding: 0.75rem;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
background: white;
}
.settings-twofa-qr img {
width: 160px;
height: 160px;
display: block;
}
.settings-twofa-meta {
flex: 1;
min-width: 0;
}
.settings-twofa-secret {
display: flex;
flex-direction: column;
gap: 0.35rem;
}
.settings-twofa-secret-label {
font-size: 0.85rem;
color: var(--color-text-secondary);
}
.settings-twofa-secret-value {
display: inline-block;
padding: 0.5rem 0.75rem;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-md);
background: var(--color-bg-card);
overflow-x: auto;
}
.settings-twofa-actions {
display: flex;
gap: 0.75rem;
align-items: center;
margin-top: 0.75rem;
flex-wrap: wrap;
}
.settings-twofa-actions-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1rem;
}
.settings-twofa-action h4 {
margin: 0 0 0.25rem;
}
.settings-twofa-action p {
margin: 0 0 0.75rem;
color: var(--color-text-secondary);
font-size: 0.9rem;
line-height: 1.5;
}
.settings-twofa-action.danger {
border: 1px solid rgba(239, 68, 68, 0.25);
border-radius: var(--radius-lg);
padding: 1rem;
background: rgba(239, 68, 68, 0.04);
}
.settings-backup-codes {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
gap: 0.5rem;
margin-top: 0.75rem;
}
.settings-backup-code {
display: inline-block;
padding: 0.5rem 0.75rem;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-md);
background: var(--color-bg-card);
text-align: center;
}
.settings-sessions-header {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 1rem;
margin-bottom: 1rem;
}
.settings-sessions-list {
display: flex;
flex-direction: column;
gap: 0.75rem;
margin-top: 0.75rem;
}
.settings-session-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 1rem;
padding: 0.85rem;
border: 1px solid var(--color-card-outline);
border-radius: var(--radius-lg);
background: var(--color-bg-card);
box-shadow: var(--shadow-sm);
}
.settings-session-meta {
min-width: 0;
flex: 1;
}
.settings-session-title {
display: flex;
align-items: center;
gap: 0.5rem;
flex-wrap: wrap;
}
.settings-session-device {
font-weight: 650;
color: var(--color-text-primary);
}
.settings-session-details {
margin-top: 0.25rem;
color: var(--color-text-secondary);
font-size: 0.85rem;
line-height: 1.4;
}
.settings-session-actions {
flex: 0 0 auto;
}
.settings-empty {
margin-top: 0.75rem;
padding: 0.85rem;
border: 1px dashed var(--color-card-outline);
border-radius: var(--radius-lg);
color: var(--color-text-secondary);
text-align: center;
}
@media (max-width: 768px) {
.settings-twofa-setup {
flex-direction: column;
align-items: stretch;
}
.settings-twofa-actions-grid {
grid-template-columns: 1fr;
}
.settings-session-row {
flex-direction: column;
}
.settings-session-actions {
width: 100%;
display: flex;
justify-content: flex-end;
}
}

View File

@@ -139,7 +139,7 @@
.sidebar.dynamic.collapsed.expanded-force .view-mode-toggle {
justify-content: flex-start;
padding: 0.75rem;
padding: 0.75rem 1rem;
gap: 0.75rem;
}
@@ -191,7 +191,7 @@
}
.sidebar.dynamic.collapsed .view-mode-toggle {
padding: 0.75rem;
padding: 0.75rem 0.5rem;
}
/* Re-enable transitions ONLY on hover or when forced expanded */
@@ -356,6 +356,15 @@
/* Taller touch target */
}
button.nav-item {
width: 100%;
background: none;
border: none;
cursor: pointer;
text-align: left;
font: inherit;
}
.sidebar.collapsed .nav-item {
justify-content: center;
padding: 0.75rem 0.5rem;
@@ -422,21 +431,50 @@
transition: opacity 0.3s ease, width 0.3s ease;
}
.nav-badge {
margin-left: auto;
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 22px;
height: 22px;
padding: 0 6px;
border-radius: 999px;
font-size: 0.75rem;
font-weight: 700;
background: rgba(239, 68, 68, 0.18);
color: #ef4444;
border: 1px solid rgba(239, 68, 68, 0.28);
}
.sidebar.collapsed .nav-badge {
position: absolute;
top: 6px;
right: 10px;
margin-left: 0;
min-width: 18px;
height: 18px;
padding: 0 4px;
font-size: 0.7rem;
}
.sidebar-bottom-actions {
padding: 0 0.75rem;
}
.sidebar-footer {
padding: 0.75rem;
padding: 0.5rem 0.75rem 0.75rem;
border-top: 1px solid var(--color-sidebar-border);
flex-shrink: 0;
display: flex;
flex-direction: column;
gap: 0;
margin-top: auto;
/* Push to bottom */
margin-left: 0;
margin-right: 0;
margin-bottom: 0;
}
.sidebar-footer>*:not(:last-child) {
.sidebar-footer>*:not(:last-child):not(.nav-item) {
margin-bottom: 0.15rem;
}
@@ -445,7 +483,8 @@
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem;
padding: 0.75rem 1rem;
margin: 0.25rem 0;
background: transparent;
border: 1px solid transparent;
border-radius: var(--radius-md);
@@ -486,7 +525,7 @@
.sidebar.collapsed .view-mode-toggle {
justify-content: center;
padding: 0.75rem;
padding: 0.75rem 0.5rem;
gap: 0;
/* Ensure no gap affects centering */
}
@@ -667,6 +706,8 @@
.sidebar.collapsed .view-mode-toggle {
justify-content: flex-start;
padding: 0.75rem 1rem;
gap: 0.75rem;
}
.sidebar.collapsed .user-info-compact {
@@ -1050,16 +1091,58 @@
}
}
/* ========== DARK THEME + AUTO ACCENT OVERRIDES ========== */
/* ========== AUTO ACCENT OVERRIDES ========== */
/* Nav items with auto accent in dark mode: use off-white background with dark text */
[data-theme='dark'][data-accent='auto'] .nav-item.active {
/*
* Sidebar has a dark background in BOTH light and dark themes.
* With auto accent color, we need high-contrast active states.
* Use off-white background with dark text for visibility.
*/
/* Nav items with auto accent: use off-white background with dark text */
[data-accent='auto'] .nav-item.active {
background: #f3f4f6;
color: #111827 !important;
box-shadow: 0 0 16px 2px rgba(243, 244, 246, 0.5);
}
[data-accent='auto'] .nav-item.active .nav-icon,
[data-accent='auto'] .nav-item.active .nav-label {
color: #111827 !important;
}
/* Active indicator bar */
[data-accent='auto'] .nav-item.active::before {
background: #111827;
}
/* Hover on active item - slightly darker */
[data-accent='auto'] .nav-item.active:hover {
background: #e5e7eb;
color: #111827 !important;
box-shadow: 0 0 20px 2px rgba(229, 231, 235, 0.4);
}
[data-theme='dark'][data-accent='auto'] .nav-item.active .nav-icon,
[data-theme='dark'][data-accent='auto'] .nav-item.active .nav-label {
color: #111827 !important;
/* Hover states for non-active items */
[data-accent='auto'] .nav-item:not(.active):hover {
background: rgba(229, 231, 235, 0.15);
}
/* View mode toggle with auto accent */
[data-accent='auto'] .view-mode-toggle:hover {
background: rgba(229, 231, 235, 0.12);
border-color: rgba(229, 231, 235, 0.2);
}
[data-accent='auto'] .view-mode-toggle.user-mode {
background: rgba(229, 231, 235, 0.18);
border-color: rgba(229, 231, 235, 0.25);
}
[data-accent='auto'] .view-mode-toggle.user-mode:hover {
background: rgba(229, 231, 235, 0.22);
border-color: rgba(229, 231, 235, 0.3);
}
/* User initial badge with auto accent */
[data-accent='auto'] .user-initial {
background: rgba(229, 231, 235, 0.25);
}

View File

@@ -544,7 +544,7 @@
}
/* Badge Styles */
.badge {
.theme-settings-root .badge {
padding: 0.35rem 0.75rem;
border-radius: var(--radius-md);
font-size: 0.8rem;
@@ -552,12 +552,13 @@
white-space: nowrap;
}
.badge-accent {
.theme-settings-root .badge-accent {
background: var(--color-accent);
color: white;
border: none;
}
.badge-success {
.theme-settings-root .badge-success {
background: rgba(34, 197, 94, 0.15);
color: #16a34a;
border: 1px solid rgba(34, 197, 94, 0.3);

View File

@@ -91,22 +91,24 @@
.users-root .users-table th,
.users-root .users-table td {
padding: var(--table-cell-padding);
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--color-card-outline);
text-align: left;
vertical-align: middle;
font-size: 0.9rem;
}
.users-root .users-table tbody tr:not(:last-child) {
border-bottom: 1px solid var(--color-card-outline);
.users-root .users-table tr:last-child td {
border-bottom: none;
}
.users-root .users-table th {
font-weight: 600;
font-size: 0.85rem;
font-weight: 700;
font-size: 0.82rem;
color: var(--color-text-secondary);
background: var(--color-bg-elevated);
text-transform: uppercase;
letter-spacing: 0.03em;
letter-spacing: 0.02em;
}
.users-root .users-table tbody tr:hover {

View File

@@ -46,6 +46,12 @@ body {
cursor: text;
}
/* Utility for monospace text (IDs, keys, timestamps) */
.mono {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
}
#root {
min-height: 100vh;
width: 100%;