1
0
forked from wrenn/wrenn
Files
wrenn-releases/frontend/src/app.css
2026-04-15 22:38:19 +06:00

194 lines
4.9 KiB
CSS

@import 'tailwindcss';
@import '@fontsource-variable/manrope';
@import '@fontsource/instrument-serif/400.css';
@import '@fontsource-variable/jetbrains-mono';
@import '@fontsource/alice/400.css';
/*
* Wrenn Design Tokens
* Sharp, warm, industrial-confident. Dark-first.
*/
@theme {
/* Background scale (6 steps, near-black-green) */
--color-bg-0: #0a0c0b;
--color-bg-1: #0f1211;
--color-bg-2: #141817;
--color-bg-3: #1a1e1c;
--color-bg-4: #212624;
--color-bg-5: #2a302d;
/* Text hierarchy (5 levels) */
--color-text-bright: #eae7e2;
--color-text-primary: #d0cdc6;
--color-text-secondary: #9b9790;
--color-text-tertiary: #6b6862;
--color-text-muted: #454340;
/* Sage green brand accent (3 tiers + 2 glows) */
--color-accent: #5e8c58;
--color-accent-mid: #89a785;
--color-accent-bright: #a4c89f;
--color-accent-glow: rgba(94, 140, 88, 0.07);
--color-accent-glow-mid: rgba(94, 140, 88, 0.14);
/* Borders (2 levels) */
--color-border: #1f2321;
--color-border-mid: #2a2f2c;
/* Semantic status */
--color-amber: #d4a73c;
--color-red: #cf8172;
--color-blue: #5a9fd4;
/* Fonts */
--font-sans: 'Manrope Variable', system-ui, sans-serif;
--font-serif: 'Instrument Serif', serif;
--font-mono: 'JetBrains Mono Variable', monospace;
--font-brand: 'Alice', serif;
/* Type scale — rem-based (root = 87.5%, giving 14px at browser default)
Heading tokens carry a default line-height; body/UI tokens inherit the global 1.6. */
--text-display: 2.571rem; /* ~36px — auth/login section headings */
--text-display--line-height: 1.1;
--text-page: 2rem; /* ~28px — page h1 titles */
--text-page--line-height: 1.15;
--text-heading: 1.429rem; /* ~20px — dialog headings, empty-state */
--text-heading--line-height: 1.25;
--text-body: 1rem; /* 14px — primary body, buttons, inputs */
--text-ui: 0.929rem; /* ~13px — nav labels, table cells, secondary */
--text-meta: 0.857rem; /* ~12px — key prefixes, minor info */
--text-label: 0.786rem; /* ~11px — uppercase section labels */
--text-badge: 0.714rem; /* ~10px — live badges, tiny indicators */
/* Radii */
--radius-card: 8px;
--radius-input: 5px;
--radius-button: 5px;
--radius-avatar: 5px;
--radius-logo: 6px;
/* Shadows */
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.2);
--shadow-card: 0 4px 12px rgba(0, 0, 0, 0.4), 0 1px 3px rgba(0, 0, 0, 0.25);
--shadow-dialog: 0 16px 48px rgba(0, 0, 0, 0.6), 0 4px 12px rgba(0, 0, 0, 0.35);
}
/* Base styles */
html {
font-family: var(--font-sans);
font-size: 87.5%; /* 14px at browser default; scales with user text-size preferences */
line-height: 1.6;
color: var(--color-text-primary);
background-color: var(--color-bg-0);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
body {
margin: 0;
min-height: 100vh;
}
/* Instrument Serif reads less condensed with a touch of positive tracking */
.font-serif {
letter-spacing: 0.015em;
}
/* Tabular figures on all mono text — numbers align in tables and metric displays */
.font-mono {
font-variant-numeric: tabular-nums;
}
/* Selection */
::selection {
background: rgba(94, 140, 88, 0.25);
color: var(--color-text-bright);
}
/* Scrollbar — thin, matches dark theme */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--color-bg-4);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--color-bg-5);
}
/* Live status dot pulse animation — opacity-only for GPU compositor, zero paint cost */
@keyframes wrenn-glow {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
/* Outward ring ripple — for live/running status dots; more delightful than opacity-only */
@keyframes status-ping {
0% {
transform: scale(1);
opacity: 0.8;
}
80%,
100% {
transform: scale(2.8);
opacity: 0;
}
}
.animate-status-ping {
animation: status-ping 2s cubic-bezier(0, 0, 0.2, 1) infinite;
will-change: transform, opacity;
}
/* Fade-up entrance animation */
@keyframes fadeUp {
from {
opacity: 0;
transform: translateY(6px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Refresh icon spin — one full rotation */
@keyframes spin-once {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Floating icon — used on empty-state icon containers */
@keyframes iconFloat {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-6px); }
}
/* Respect user motion preferences — covers both CSS class animations and inline style animations */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}