Implement M1.5 visual design foundation: tokens, IBM Plex, theme toggle, chart themes

This commit is contained in:
2026-06-05 01:29:10 +03:00
parent 547edb85e4
commit 22f0556ef8
31 changed files with 713 additions and 136 deletions
+39 -2
View File
@@ -1,5 +1,26 @@
@import './tokens.css';
/*
* IBM Plex, self-hosted via @fontsource — offline/PWA safe, never a CDN
* (docs/architecture/09 §3.1). Sans: 400 body, 600 emphasis/headings, 300 for
* large display only. Mono: 400 editor/code, 500 for emphasis. Keep weights
* minimal — add one only when a surface needs it.
*
* The family-level import pulls every script subset (latin, latin-ext, cyrillic,
* greek, vietnamese). We keep them all: user data — snippet names, dataset
* values, chart labels — can be in any language, and Plex must render it rather
* than fall back to system-ui. @font-face `unicode-range` means the browser only
* *downloads* the subset a glyph needs, so the unused subsets cost nothing at
* runtime; they only add to the offline precache, which is the price of working
* internationally offline. Vite bundles the woff2 and Workbox precaches them
* (woff2 is in the PWA globPatterns — see vite.config.ts).
*/
@import '@fontsource/ibm-plex-sans/300.css';
@import '@fontsource/ibm-plex-sans/400.css';
@import '@fontsource/ibm-plex-sans/600.css';
@import '@fontsource/ibm-plex-mono/400.css';
@import '@fontsource/ibm-plex-mono/500.css';
* {
box-sizing: border-box;
}
@@ -14,8 +35,24 @@ body,
body {
font-family: var(--font-sans);
font-size: var(--font-size-base);
color: var(--color-text);
background: var(--color-bg);
/* Plex "requires space to breathe" — keep body line-height generous (doc §3.1). */
line-height: 1.45;
color: var(--text);
background: var(--bg);
/* Repaint chrome on theme flip; neutralized under reduced-motion below. */
transition:
background var(--dur-moderate) var(--ease),
color var(--dur-moderate) var(--ease);
}
/*
* Shared keyboard focus ring — always visible, accessibility is non-negotiable
* (doc §4, principle 4). Components may override the offset (e.g. inset on
* fields) but should not remove it.
*/
:where(button, input, select, textarea, a, [tabindex]):focus-visible {
outline: 2px solid var(--focus);
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {