feat(ui): Design-Tokens, Schriften und Datumsformate (#002)
Die Farben des Tresor-Designs stehen als CSS-Variablen in :root und werden per @theme inline an Tailwind gereicht, damit Inline-SVGs und Utility-Klassen dieselbe Quelle nutzen. Schriften kommen selbst gehostet aus @fontsource, nur in den benutzten Gewichten und im Latin-Ausschnitt. src/lib/format.ts rechnet fest in Europe/Berlin: der Server laeuft im Container auf UTC, die Anzeige soll aber ueberall dieselbe Ortszeit zeigen. relativ() nimmt den Bezugspunkt als Parameter, damit statische Seiten und Tests deterministisch bleiben. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1,104 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
/*
|
||||
* Design „Tresor“ (#002): Graphit-Flächen, eine Markenfarbe (Messing), Monospace für alles
|
||||
* Technische. Die Werte stehen als CSS-Variablen in :root, damit auch Inline-SVGs und
|
||||
* Stile ausserhalb von Tailwind dieselben Tokens nutzen; @theme reicht sie an Tailwind
|
||||
* weiter (bg-surface, text-muted, border-strong …).
|
||||
*
|
||||
* Es gibt bewusst nur den dunklen Modus. Ein heller folgt in einer eigenen Phase (PLAN §5).
|
||||
*/
|
||||
:root {
|
||||
--bg: #0d1013;
|
||||
--sidebar: #11151a;
|
||||
--surface: #151a1f;
|
||||
--raised: #1d232a;
|
||||
--border: #222930;
|
||||
--border-strong: #2a323b;
|
||||
--text: #e8ecef;
|
||||
--text-muted: #8b96a3;
|
||||
--accent: #f0b43c;
|
||||
--accent-soft: #3a2e14;
|
||||
--ok: #3cc9a7;
|
||||
--danger: #f2714b;
|
||||
--danger-soft: #2a1814;
|
||||
--danger-border: #6b3324;
|
||||
--info: #6aa8ff;
|
||||
|
||||
--schrift-display: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
|
||||
--schrift-text: "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;
|
||||
--schrift-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
|
||||
|
||||
--seitenleiste-breite: 248px;
|
||||
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
/* inline: Tailwind-Klassen verweisen auf die Variablen statt die Werte zu kopieren. */
|
||||
@theme inline {
|
||||
--color-bg: var(--bg);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-surface: var(--surface);
|
||||
--color-raised: var(--raised);
|
||||
--color-border: var(--border);
|
||||
--color-border-strong: var(--border-strong);
|
||||
--color-text: var(--text);
|
||||
--color-muted: var(--text-muted);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-soft: var(--accent-soft);
|
||||
--color-ok: var(--ok);
|
||||
--color-danger: var(--danger);
|
||||
--color-danger-soft: var(--danger-soft);
|
||||
--color-danger-border: var(--danger-border);
|
||||
--color-info: var(--info);
|
||||
|
||||
--font-display: var(--schrift-display);
|
||||
--font-sans: var(--schrift-text);
|
||||
--font-mono: var(--schrift-mono);
|
||||
|
||||
--radius-karte: 16px;
|
||||
--radius-box: 12px;
|
||||
--radius-feld: 10px;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
font-family: var(--schrift-text);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100dvh;
|
||||
background: var(--bg);
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-family: var(--schrift-display);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
/* Fokus immer sichtbar und in Messing – auch auf Elementen ohne eigenen Fokusstil. */
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 2px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--accent-soft);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
+18
-1
@@ -1,10 +1,27 @@
|
||||
import type { Metadata } from "next";
|
||||
import type { Metadata, Viewport } from "next";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
// Schriften selbst gehostet (#002): keine CDNs, nur die Gewichte, die das Design nutzt,
|
||||
// und nur der Latin-Ausschnitt (enthält die deutschen Umlaute und ß).
|
||||
import "@fontsource/space-grotesk/latin-500.css";
|
||||
import "@fontsource/space-grotesk/latin-600.css";
|
||||
import "@fontsource/space-grotesk/latin-700.css";
|
||||
import "@fontsource/ibm-plex-sans/latin-400.css";
|
||||
import "@fontsource/ibm-plex-sans/latin-500.css";
|
||||
import "@fontsource/ibm-plex-sans/latin-600.css";
|
||||
import "@fontsource/jetbrains-mono/latin-400.css";
|
||||
import "@fontsource/jetbrains-mono/latin-500.css";
|
||||
import "./globals.css";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: { default: "SSHKeyVault", template: "%s · SSHKeyVault" },
|
||||
description: "Zentrale Verwaltung von SSH-Schlüsseln",
|
||||
applicationName: "SSHKeyVault",
|
||||
};
|
||||
|
||||
export const viewport: Viewport = {
|
||||
themeColor: "#0D1013",
|
||||
colorScheme: "dark",
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
|
||||
Reference in New Issue
Block a user