165 lines
5.3 KiB
CSS
165 lines
5.3 KiB
CSS
/* ══════════════════════════════════════════════════════════════════════
|
|
Design tokens — shared by every theme.
|
|
Themes (src/themes/*.css) set the palette (`--color-*`) and may override
|
|
any of the shape/type/depth tokens below; App.css only consumes tokens.
|
|
The emails read them too (api/mail/theme-tokens.ts), from the rules on
|
|
the root element only: a token a `prefers-color-scheme` block sets must
|
|
also be set under `[data-color-scheme]`, as the themes do.
|
|
══════════════════════════════════════════════════════════════════════ */
|
|
|
|
:root {
|
|
/* ── Color scheme ──
|
|
`light-dark()` in the theme palettes resolves against this, so a single
|
|
palette block covers auto, forced-light and forced-dark. */
|
|
color-scheme: light dark;
|
|
|
|
font-family: var(--font-body);
|
|
font-optical-sizing: auto;
|
|
font-weight: 400;
|
|
font-style: normal;
|
|
line-height: 1.5;
|
|
|
|
/* ── Space (4px grid) ── */
|
|
--space-1: 0.25rem;
|
|
--space-2: 0.5rem;
|
|
--space-3: 0.75rem;
|
|
--space-4: 1rem;
|
|
--space-5: 1.25rem;
|
|
--space-6: 1.5rem;
|
|
--space-7: 2rem;
|
|
--space-8: 3rem;
|
|
|
|
/* ── Radius ── */
|
|
--radius-xs: 3px;
|
|
--radius-sm: 4px;
|
|
--radius-md: 6px;
|
|
--radius-lg: 8px;
|
|
--radius-xl: 12px;
|
|
--radius-full: 999px;
|
|
|
|
/* ── Type scale ── */
|
|
--text-2xs: 0.7rem;
|
|
--text-xs: 0.78rem;
|
|
--text-sm: 0.85rem;
|
|
--text-md: 0.92rem;
|
|
--text-base: 1rem;
|
|
--text-lg: 1.15rem;
|
|
--text-xl: 1.25rem;
|
|
--text-2xl: 1.5rem;
|
|
--text-3xl: 2rem;
|
|
--text-display: 3rem;
|
|
|
|
--leading-tight: 1.2;
|
|
--leading-snug: 1.35;
|
|
--leading-normal: 1.5;
|
|
|
|
--weight-regular: 400;
|
|
--weight-medium: 500;
|
|
--weight-semibold: 600;
|
|
--weight-bold: 700;
|
|
|
|
--tracking-caps: 0.06em;
|
|
|
|
/* ── Fonts ── */
|
|
--font-body: system-ui, sans-serif;
|
|
--font-display: var(--font-body);
|
|
--font-mono: ui-monospace, "SFMono-Regular", Menlo, monospace;
|
|
|
|
/* ── Service brand colors ──
|
|
Fixed across themes and schemes. `on-brand` is the foreground for text
|
|
sitting on any of them — also fixed, so contrast never flips. */
|
|
--color-youtube: #c00;
|
|
--color-youtube-hover: #f00;
|
|
--color-bandcamp: #1da0c3;
|
|
--color-bandcamp-hover: #25c8f0;
|
|
--color-soundcloud: #f50;
|
|
--color-soundcloud-hover: #f73;
|
|
--color-on-brand: #fff;
|
|
|
|
/* ── Elevation ── */
|
|
--shadow-1: 0 1px 2px rgb(0 0 0 / 0.12);
|
|
--shadow-2: 0 4px 16px rgb(0 0 0 / 0.2);
|
|
--shadow-3: 0 8px 32px rgb(0 0 0 / 0.45), 0 2px 8px rgb(0 0 0 / 0.3);
|
|
--shadow-focus: 0 0 0 3px var(--color-focus-ring);
|
|
|
|
/* ── Motion ── */
|
|
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
|
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
|
--dur-fast: 0.12s;
|
|
--dur-base: 0.15s;
|
|
--dur-slow: 0.2s;
|
|
--dur-reveal: 0.25s;
|
|
/* A hover lift long enough not to snap, and the slower fade that brings the
|
|
idle rocking in over the top of it. */
|
|
--dur-lift: 0.4s;
|
|
--dur-bob-fade: 0.9s;
|
|
|
|
/* ── Layers ── */
|
|
--z-raised: 1;
|
|
--z-sticky: 100;
|
|
--z-dropdown: 200;
|
|
--z-fab: 900;
|
|
--z-modal: 1000;
|
|
--z-popover: 1100;
|
|
--z-toast: 9999;
|
|
|
|
/* ── Borders ── */
|
|
--border-width: 2px;
|
|
|
|
/* ── Derived colors ──
|
|
Defaults reproduce the flat two-level (bg / surface) look; a theme that
|
|
wants more depth sets its own raised/sunken tiers. */
|
|
--color-surface-raised: var(--color-surface);
|
|
--color-surface-sunken: var(--color-bg);
|
|
--color-accent-soft: color-mix(in srgb, var(--color-accent) 14%, transparent);
|
|
--color-focus-ring: color-mix(in srgb, var(--color-accent) 45%, transparent);
|
|
/* Small labels such as "private" on one's own dump; the emails' pills too. */
|
|
--color-badge-bg: color-mix(in srgb, var(--color-text-muted) 18%, transparent);
|
|
--color-warning: #d4a017;
|
|
--color-on-danger: #fff;
|
|
|
|
/* ── Component skins ──
|
|
Knobs for the handful of treatments themes disagree on. */
|
|
--header-bg: var(--color-surface);
|
|
--card-border: var(--color-border);
|
|
--card-border-width: var(--border-width);
|
|
--card-shadow: 0 0 #0000;
|
|
--panel-ring: 0 0 #0000;
|
|
--card-hover-border: var(--color-accent);
|
|
--input-focus-bg: color-mix(
|
|
in srgb,
|
|
var(--color-accent) 4%,
|
|
var(--color-surface-sunken) 96%
|
|
);
|
|
--overlay-filter: none;
|
|
--modal-border: transparent;
|
|
--tab-border: var(--color-border);
|
|
--tab-active-bg: var(--color-accent);
|
|
--tab-active-fg: var(--color-on-accent);
|
|
--tab-text-transform: uppercase;
|
|
--tab-tracking: 0.04em;
|
|
/* The header's line icons (NavIcons.tsx): their weight and ends, and how
|
|
much of the accent washes their bodies at rest. */
|
|
--nav-icon-stroke: 1.75;
|
|
--nav-icon-linecap: round;
|
|
--nav-icon-linejoin: round;
|
|
--nav-icon-tint-strength: 22%;
|
|
--btn-primary-shadow: 0 2px 8px
|
|
color-mix(in srgb, var(--color-accent) 40%, transparent);
|
|
--btn-primary-shadow-hover: 0 4px 14px
|
|
color-mix(in srgb, var(--color-accent) 50%, transparent);
|
|
|
|
/* Legacy names still referenced by a few rules. */
|
|
--color-muted: var(--color-text-muted);
|
|
--color-error: var(--color-danger);
|
|
--color-surface-alt: var(--color-surface-raised);
|
|
}
|
|
|
|
:root[data-color-scheme="light"] {
|
|
color-scheme: light;
|
|
}
|
|
|
|
:root[data-color-scheme="dark"] {
|
|
color-scheme: dark;
|
|
}
|