Full self-hosted port of the Elydora tamper-evident audit protocol: - Hono API server with PostgreSQL, Redis, MinIO adapters - Ed25519 signed operations, chain hashing, Merkle epoch rollups - PBKDF2 password hashing, HMAC-SHA256 JWT, 5-role RBAC - Next.js management console - Node.js, Python, and Go SDKs - Docker Compose for local deployment - Helm chart for Kubernetes - Comprehensive security hardening and audit fixes applied Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
356 lines
7.6 KiB
CSS
356 lines
7.6 KiB
CSS
@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500;600;700;800&family=JetBrains+Mono:wght@300;400;500&family=Noto+Sans+SC:wght@300;400;500;600;700;800&display=swap');
|
|
|
|
@import "tailwindcss";
|
|
|
|
:root {
|
|
--bg-color: #EAEAE5;
|
|
--surface-color: #F2F2EE;
|
|
--ink-color: #121212;
|
|
--ink-dim: #666666;
|
|
--border-color: #C0C0BA;
|
|
--grid-line: rgba(18, 18, 18, 0.08);
|
|
--white: #FFFFFF;
|
|
--sidebar-width: 260px;
|
|
}
|
|
|
|
@theme inline {
|
|
--color-bg: var(--bg-color);
|
|
--color-surface: var(--surface-color);
|
|
--color-ink: var(--ink-color);
|
|
--color-ink-dim: var(--ink-dim);
|
|
--color-border: var(--border-color);
|
|
--color-grid-line: var(--grid-line);
|
|
--font-sans: 'Manrope', 'Noto Sans SC', sans-serif;
|
|
--font-mono: 'JetBrains Mono', 'Noto Sans SC', monospace;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
background-color: var(--bg-color);
|
|
color: var(--ink-color);
|
|
font-family: 'Manrope', sans-serif;
|
|
margin: 0;
|
|
overflow-x: hidden;
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
}
|
|
|
|
:lang(zh) body,
|
|
:lang(zh-CN) body,
|
|
:lang(zh-TW) body {
|
|
font-family: 'Noto Sans SC', 'Manrope', sans-serif;
|
|
}
|
|
|
|
/* Scrollbar */
|
|
::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
::-webkit-scrollbar-track {
|
|
background: var(--bg-color);
|
|
}
|
|
::-webkit-scrollbar-thumb {
|
|
background: var(--ink-color);
|
|
}
|
|
|
|
/* Grid background */
|
|
.grid-bg {
|
|
background-image:
|
|
linear-gradient(var(--grid-line) 1px, transparent 1px),
|
|
linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
|
|
background-size: 40px 40px;
|
|
}
|
|
|
|
/* Crosshair markers */
|
|
.crosshair {
|
|
position: absolute;
|
|
width: 11px;
|
|
height: 11px;
|
|
z-index: 10;
|
|
pointer-events: none;
|
|
}
|
|
.crosshair::before, .crosshair::after {
|
|
content: '';
|
|
position: absolute;
|
|
background-color: var(--ink-color);
|
|
}
|
|
.crosshair::before { width: 1px; height: 100%; left: 5px; }
|
|
.crosshair::after { height: 1px; width: 100%; top: 5px; }
|
|
|
|
.ch-tl { top: -12px; left: -12px; }
|
|
.ch-tr { top: -12px; right: -12px; }
|
|
.ch-bl { bottom: -12px; left: -12px; }
|
|
.ch-br { bottom: -12px; right: -12px; }
|
|
|
|
@media (max-width: 640px) {
|
|
.crosshair { display: none; }
|
|
}
|
|
|
|
/* Display text */
|
|
.display-text {
|
|
font-size: clamp(2.5rem, 5vw, 4.5rem);
|
|
line-height: 1.1;
|
|
letter-spacing: -0.04em;
|
|
}
|
|
|
|
/* Console display - smaller variant */
|
|
.console-display {
|
|
font-size: clamp(1.5rem, 3vw, 2.5rem);
|
|
line-height: 1.1;
|
|
letter-spacing: -0.03em;
|
|
}
|
|
|
|
/* Navigation item */
|
|
.nav-item {
|
|
position: relative;
|
|
padding-left: 1rem;
|
|
transition: all 0.3s ease;
|
|
}
|
|
.nav-item::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: 50%;
|
|
width: 4px;
|
|
height: 4px;
|
|
background: var(--ink-color);
|
|
transform: translateY(-50%) scale(0);
|
|
transition: transform 0.2s ease;
|
|
}
|
|
.nav-item:hover {
|
|
padding-left: 1.5rem;
|
|
color: var(--ink-color);
|
|
}
|
|
.nav-item:hover::before {
|
|
transform: translateY(-50%) scale(1);
|
|
}
|
|
|
|
/* Sidebar navigation item */
|
|
.sidebar-nav-item {
|
|
position: relative;
|
|
padding: 8px 16px;
|
|
font-family: 'JetBrains Mono', 'Noto Sans SC', monospace;
|
|
font-size: 12px;
|
|
font-weight: 400;
|
|
letter-spacing: 0.02em;
|
|
color: rgba(234, 234, 229, 0.6);
|
|
transition: all 0.2s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
}
|
|
.sidebar-nav-item:hover {
|
|
color: #EAEAE5;
|
|
background: rgba(234, 234, 229, 0.05);
|
|
}
|
|
.sidebar-nav-item.active {
|
|
color: #EAEAE5;
|
|
background: rgba(234, 234, 229, 0.08);
|
|
}
|
|
.sidebar-nav-item.active::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: 4px;
|
|
bottom: 4px;
|
|
width: 2px;
|
|
background: #EAEAE5;
|
|
}
|
|
|
|
/* Marquee */
|
|
.marquee-container {
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
}
|
|
.marquee-content {
|
|
display: inline-block;
|
|
animation: marquee 40s linear infinite;
|
|
}
|
|
@keyframes marquee {
|
|
0% { transform: translateX(0); }
|
|
100% { transform: translateX(-50%); }
|
|
}
|
|
|
|
/* Brutalist button */
|
|
.btn-brutalist {
|
|
background: var(--ink-color);
|
|
color: var(--bg-color);
|
|
border: 1px solid var(--ink-color);
|
|
transition: all 0.2s cubic-bezier(0.25, 1, 0.5, 1);
|
|
position: relative;
|
|
overflow: hidden;
|
|
cursor: pointer;
|
|
font-family: 'JetBrains Mono', 'Noto Sans SC', monospace;
|
|
font-weight: 700;
|
|
font-size: 11px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
padding: 10px 24px;
|
|
}
|
|
.btn-brutalist:hover {
|
|
background: transparent;
|
|
color: var(--ink-color);
|
|
}
|
|
.btn-brutalist:disabled {
|
|
opacity: 0.4;
|
|
cursor: not-allowed;
|
|
}
|
|
.btn-brutalist:disabled:hover {
|
|
background: var(--ink-color);
|
|
color: var(--bg-color);
|
|
}
|
|
|
|
/* Ghost button */
|
|
.btn-ghost {
|
|
background: transparent;
|
|
color: var(--ink-color);
|
|
border: 1px solid var(--border-color);
|
|
transition: all 0.2s cubic-bezier(0.25, 1, 0.5, 1);
|
|
cursor: pointer;
|
|
font-family: 'JetBrains Mono', 'Noto Sans SC', monospace;
|
|
font-weight: 700;
|
|
font-size: 11px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
padding: 10px 24px;
|
|
}
|
|
.btn-ghost:hover {
|
|
background: var(--bg-color);
|
|
border-color: var(--ink-color);
|
|
}
|
|
.btn-ghost:disabled {
|
|
opacity: 0.4;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
/* Data row */
|
|
.data-row {
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
.data-row:hover {
|
|
background-color: #FFFFFF;
|
|
}
|
|
|
|
/* Feature card */
|
|
.feature-card {
|
|
transition: all 0.3s ease;
|
|
}
|
|
.feature-card:hover {
|
|
background-color: #FFFFFF;
|
|
}
|
|
|
|
/* Stat card */
|
|
.stat-card {
|
|
background: var(--surface-color);
|
|
border: 1px solid var(--border-color);
|
|
padding: 24px;
|
|
position: relative;
|
|
transition: all 0.3s ease;
|
|
}
|
|
.stat-card:hover {
|
|
background: #FFFFFF;
|
|
}
|
|
|
|
/* Loading bar animation */
|
|
@keyframes load {
|
|
0% { transform: scaleX(0); }
|
|
50% { transform: scaleX(0.7); }
|
|
100% { transform: scaleX(0); transform-origin: right; }
|
|
}
|
|
|
|
/* Fade in animation */
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
.fade-in {
|
|
animation: fadeIn 0.6s ease forwards;
|
|
}
|
|
|
|
/* Stagger children */
|
|
.stagger-children > * {
|
|
opacity: 0;
|
|
animation: fadeIn 0.5s ease forwards;
|
|
}
|
|
.stagger-children > *:nth-child(1) { animation-delay: 0.1s; }
|
|
.stagger-children > *:nth-child(2) { animation-delay: 0.2s; }
|
|
.stagger-children > *:nth-child(3) { animation-delay: 0.3s; }
|
|
.stagger-children > *:nth-child(4) { animation-delay: 0.4s; }
|
|
.stagger-children > *:nth-child(5) { animation-delay: 0.5s; }
|
|
.stagger-children > *:nth-child(6) { animation-delay: 0.6s; }
|
|
|
|
/* Skeleton loading */
|
|
@keyframes shimmer {
|
|
0% { background-position: -200% 0; }
|
|
100% { background-position: 200% 0; }
|
|
}
|
|
.skeleton {
|
|
background: linear-gradient(90deg, var(--border-color) 25%, var(--surface-color) 50%, var(--border-color) 75%);
|
|
background-size: 200% 100%;
|
|
animation: shimmer 1.5s ease-in-out infinite;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
/* Pulse dot animation */
|
|
@keyframes pulse-dot {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.4; }
|
|
}
|
|
.pulse-dot {
|
|
animation: pulse-dot 2s ease-in-out infinite;
|
|
}
|
|
|
|
/* Modal overlay */
|
|
.modal-overlay {
|
|
background: transparent;
|
|
}
|
|
|
|
/* Section label */
|
|
.section-label {
|
|
font-family: 'JetBrains Mono', 'Noto Sans SC', monospace;
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.15em;
|
|
color: var(--ink-dim);
|
|
}
|
|
|
|
/* Table header */
|
|
.table-header {
|
|
font-family: 'JetBrains Mono', 'Noto Sans SC', monospace;
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
color: var(--ink-dim);
|
|
}
|
|
|
|
/* Monospace data */
|
|
.mono-data {
|
|
font-family: 'JetBrains Mono', 'Noto Sans SC', monospace;
|
|
font-size: 13px;
|
|
font-weight: 400;
|
|
overflow-wrap: break-word;
|
|
word-break: break-all;
|
|
}
|
|
|
|
/* Mobile-friendly table cells */
|
|
@media (max-width: 640px) {
|
|
.stat-card {
|
|
padding: 16px;
|
|
}
|
|
}
|
|
|
|
/* Checkbox/check icon */
|
|
.check-pass {
|
|
color: #16a34a;
|
|
}
|
|
.check-fail {
|
|
color: #dc2626;
|
|
}
|