Raiju/css/raiju-admin-tokens.css
2026-10-25 06:05:42 +03:00

757 lines
36 KiB
CSS

/*
* Raiju Admin Design Tokens
* Shared across admin backend + inline editor.
* Prefix: --rj-* to avoid collision with frontend site CSS.
*/
/* ============================================================
LIGHT THEME (default)
============================================================ */
:root,
[data-site-theme="light"] {
/* Brand */
--rj-brand: #b45309;
--rj-brand-dark: #92400e;
--rj-brand-darker: #78350f;
--rj-brand-light: #f59e0b;
--rj-brand-subtle: #fff7ed;
/* Primary (interactive elements) */
--rj-primary: #3858e9;
--rj-primary-hover: #2745d8;
--rj-primary-active: #2038b8;
--rj-primary-btn: radial-gradient(ellipse at 50% 0%, #6b7ff0 0%, #3858e9 70%);
--rj-primary-btn-hover: radial-gradient(ellipse at 50% 0%, #8496f3 0%, #3858e9 70%);
/* Glow: a white sheen painted over the button colour (so the colour below can animate) */
--rj-primary-sheen: radial-gradient(ellipse at 50% 0%, rgba(255, 255, 255, 0.28) 0%, rgba(255, 255, 255, 0) 70%);
/* Hover: the fill brightens briefly (lift), then settles a little above the rest colour.
Fallbacks mix with white; the @supports block below derives them in OKLCH. */
--rj-hover-lift: color-mix(in srgb, var(--rj-primary) 90%, white);
--rj-hover-settle: color-mix(in srgb, var(--rj-primary) 95%, white);
/* Tinted hover for outlined and quiet controls, derived from the surface they sit on */
--rj-hover-tint: color-mix(in srgb, var(--rj-primary) 16%, var(--rj-bg-elevated));
--rj-hover-tint-settle: color-mix(in srgb, var(--rj-primary) 9%, var(--rj-bg-elevated));
--rj-primary-subtle: rgba(56, 88, 233, 0.08);
--rj-primary-muted: rgba(56, 88, 233, 0.15);
--rj-primary-medium: rgba(56, 88, 233, 0.30);
/* Neutral surfaces */
--rj-bg: #f3f7fe;
--rj-bg-elevated: #ffffff;
--rj-bg-sunken: #e7effd;
--rj-bg-hover: #edf3fd;
--rj-sidebar-bg: #e4ecfd;
--rj-surface-panel: var(--rj-bg-elevated);
/* Semantic base colours: red for danger, yellow for warnings, green
for success. "Erweitert" may override each; success follows the
primary colour unless a site picks its own. The derived shades live
in the @supports block below. */
--rj-danger-base: #dc2626;
--rj-warning-base: #d97706;
--rj-success-base: var(--rj-primary);
/* Base colour: the one colour a site picks. Everything interactive and
every tinted surface derives from it (see THEME PRESETS below). The
accent base defaults to the base colour; "Erweitert" may override it. */
--rj-base: #3858e9;
--rj-accent-base: var(--rj-base);
/* Shell chrome (sidebar + topbar). Presets recolour these; the admin
stylesheet only ever reads them. */
--rj-sidebar-text: var(--rj-text-secondary);
--rj-sidebar-text-active: var(--rj-primary);
/* Hover text in the sidebar; presets whose active item sits on the primary colour set their own */
--rj-sidebar-text-hover: var(--rj-sidebar-text-active);
--rj-sidebar-hover-bg: var(--rj-primary-subtle);
--rj-sidebar-active-bg: var(--rj-primary-subtle);
--rj-sidebar-border: rgba(0, 0, 0, 0.06);
--rj-topbar-bg: var(--rj-sidebar-bg);
--rj-topbar-text: var(--rj-text);
--rj-topbar-text-muted: var(--rj-text-secondary);
--rj-topbar-border: transparent;
--rj-topbar-divider: var(--rj-border);
--rj-surface-group: color-mix(in srgb, var(--rj-bg-elevated) 88%, var(--rj-bg));
--rj-surface-item: var(--rj-bg);
/* Text */
--rj-text: #1a1a1a;
--rj-text-secondary: #454545;
--rj-text-muted: #595959;
--rj-text-on-primary: #ffffff;
/* Borders */
--rj-border: #ccd9ed;
--rj-border-strong: #adbfd9;
--rj-border-subtle: color-mix(in srgb, var(--rj-border) 62%, transparent);
--rj-border-focus: var(--rj-primary);
--rj-focus-ring: var(--rj-primary-muted);
/* Semantic */
--rj-success: #3858e9;
--rj-success-subtle: #eff6ff;
--rj-danger: #dc2626;
--rj-danger-hover: #b91c1c;
--rj-danger-subtle: #fef2f2;
--rj-danger-btn: radial-gradient(ellipse at 50% 0%, #ef4444 0%, #b91c1c 70%);
--rj-danger-btn-hover: radial-gradient(ellipse at 50% 0%, #f87171 0%, #dc2626 70%);
--rj-warning: #d97706;
--rj-warning-subtle: #fffbeb;
--rj-warning-text: #92400e;
--rj-warning-text-strong: #78350f;
/* Shadows (blue-tinted, layered) */
--rj-shadow-sm: 0 1px 2px rgba(37, 99, 235, 0.04), 0 1px 3px rgba(0, 0, 0, 0.06);
--rj-shadow-md: 0 2px 4px rgba(37, 99, 235, 0.04), 0 4px 12px rgba(0, 0, 0, 0.08);
--rj-shadow-lg: 0 4px 8px rgba(37, 99, 235, 0.04), 0 8px 24px rgba(0, 0, 0, 0.12);
--rj-shadow-xl: 0 8px 16px rgba(37, 99, 235, 0.06), 0 16px 48px rgba(0, 0, 0, 0.16);
/* Typography */
--rj-font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
--rj-font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
--rj-font-display: var(--rj-font-sans);
/* Density factor. The admin sets it from the viewport or the user's
"Dichte" setting (see admin/style.css); everywhere else it is 1.
It scales spacing and control heights, never font sizes. */
--rj-d: 1;
/* Spacing (4px grid, scaled by density). Values in comments are for
--rj-d: 1 at 16px root size. */
--rj-space-0-5: calc(0.125rem * var(--rj-d, 1)); /* 2px */
--rj-space-1: calc(0.25rem * var(--rj-d, 1)); /* 4px */
--rj-space-1-5: calc(0.375rem * var(--rj-d, 1)); /* 6px */
--rj-space-2: calc(0.5rem * var(--rj-d, 1)); /* 8px */
--rj-space-2-5: calc(0.625rem * var(--rj-d, 1)); /* 10px */
--rj-space-3: calc(0.75rem * var(--rj-d, 1)); /* 12px */
--rj-space-3-5: calc(0.875rem * var(--rj-d, 1)); /* 14px */
--rj-space-4: calc(1rem * var(--rj-d, 1)); /* 16px */
--rj-space-5: calc(1.25rem * var(--rj-d, 1)); /* 20px */
--rj-space-6: calc(1.5rem * var(--rj-d, 1)); /* 24px */
--rj-space-8: calc(2rem * var(--rj-d, 1)); /* 32px */
--rj-space-10: calc(2.5rem * var(--rj-d, 1)); /* 40px */
--rj-space-12: calc(3rem * var(--rj-d, 1)); /* 48px */
/* Type scale: six steps. Size separates the levels, weight is secondary.
--rj-font-scale (the "Schriftgröße" setting, data-font-size on <html>)
multiplies the steps only; spacing and control heights stay as they are. */
--rj-font-scale: 1;
--rj-text-xs: calc(0.75rem * var(--rj-font-scale)); /* table heads, group labels, meta, pills */
--rj-text-sm: calc(0.8125rem * var(--rj-font-scale)); /* hints, descriptions */
--rj-text-md: calc(0.875rem * var(--rj-font-scale)); /* body, labels, buttons, inputs */
--rj-text-lg: calc(1rem * var(--rj-font-scale)); /* h3 card titles */
--rj-text-xl: calc(1.375rem * var(--rj-font-scale)); /* h2 page titles */
--rj-text-2xl: calc(1.75rem * var(--rj-font-scale)); /* stat numbers */
/* Controls: one height for inputs, selects and buttons, one small
variant for toolbars and table rows. */
--rj-control-h: calc(2.25rem * var(--rj-d, 1) + 0.25rem); /* 40px */
--rj-control-h-sm: calc(1.75rem * var(--rj-d, 1) + 0.25rem); /* 32px */
/* Admin shell geometry (rem so it grows with the root font size) */
--rj-sidebar-w: 12.5rem; /* 200px */
--rj-topbar-h: 3.0625rem; /* 49px */
--rj-content-max: 100rem; /* 1600px at 16px root */
/* Group dividers (settings groups, sidebar foot, save bars): solid by
default, Console switches them to dashed */
--rj-divider-style: solid;
/* Border radii */
--rj-radius-sm: 4px;
--rj-radius-md: 6px;
--rj-radius-lg: 10px;
--rj-radius-xl: 16px;
--rj-radius-full: 9999px;
/* Transitions */
--rj-ease: cubic-bezier(0.22, 1, 0.36, 1);
--rj-duration-fast: 150ms;
--rj-duration-normal: 200ms;
/* Hover motion: rise to the peak, hold it, then settle; leave calmly, press at once.
The in-duration covers the whole rise-hold-settle run of @keyframes rj-hover-fill. */
--rj-ease-overshoot: cubic-bezier(0.16, 2.3, 0.4, 1);
--rj-duration-hover-in: 1400ms;
--rj-duration-hover-out: 320ms;
--rj-duration-press: 100ms;
/* Z-index layers */
--rj-z-dropdown: 100;
--rj-z-sticky: 500;
--rj-z-adminbar: 10000;
--rj-z-modal: 20000;
--rj-z-toast: 30000;
}
/* ============================================================
DARK THEME
============================================================ */
[data-site-theme="dark"] {
--rj-bg: #151c28;
--rj-bg-elevated: #1e2632;
--rj-bg-sunken: #0c121e;
--rj-bg-hover: #253040;
--rj-sidebar-bg: #0e1420;
--rj-surface-panel: var(--rj-bg-elevated);
--rj-sidebar-border: rgba(255, 255, 255, 0.06);
--rj-surface-group: color-mix(in srgb, var(--rj-bg-elevated) 82%, var(--rj-bg));
--rj-surface-item: var(--rj-bg);
--rj-text: #e5e5e5;
--rj-text-secondary: #b8b8b8;
--rj-text-muted: #909090;
--rj-border: #344255;
--rj-border-strong: #46566d;
--rj-border-subtle: color-mix(in srgb, var(--rj-border) 58%, transparent);
--rj-primary: #6b7ff0;
--rj-primary-hover: #8496f3;
--rj-primary-active: #3858e9;
--rj-primary-subtle: rgba(56, 88, 233, 0.12);
--rj-primary-muted: rgba(56, 88, 233, 0.22);
--rj-brand-subtle: rgba(180, 83, 9, 0.16);
--rj-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--rj-shadow-md: 0 2px 8px rgba(0, 0, 0, 0.4);
--rj-shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.5);
--rj-shadow-xl: 0 8px 32px rgba(0, 0, 0, 0.6);
--rj-success-subtle: rgba(37, 99, 235, 0.1);
--rj-danger-subtle: rgba(220, 38, 38, 0.1);
--rj-warning-subtle: rgba(217, 119, 6, 0.1);
--rj-warning-text: #fbbf24;
--rj-warning-text-strong: #fcd34d;
}
/* ============================================================
THEME PRESETS + BASE COLOUR DERIVATION
------------------------------------------------------------
Needs relative colour syntax (Chrome 119, Safari 16.4, Firefox 128).
Older browsers keep the static values above. The <html> element carries
data-theme-preset="soft|classic|paper|studio|console|pop" (default soft),
data-font="system|inter|plex|atkinson|public|geist-mono", data-font-size and data-density; admin/dashboard.php
sets --rj-base / --rj-accent-base inline from the saved settings.
============================================================ */
@supports (color: oklch(from red l c h)) {
/* --- Interactive colour, every preset, light --- */
:root,
[data-site-theme="light"] {
--rj-primary-src: var(--rj-base);
--rj-primary: oklch(from var(--rj-primary-src) l c h);
--rj-primary-hover: oklch(from var(--rj-primary-src) calc(l - 0.06) c h);
--rj-primary-active: oklch(from var(--rj-primary-src) calc(l - 0.11) c h);
--rj-primary-subtle: oklch(from var(--rj-primary-src) l c h / 0.09);
--rj-primary-muted: oklch(from var(--rj-primary-src) l c h / 0.17);
--rj-primary-medium: oklch(from var(--rj-primary-src) l c h / 0.30);
--rj-primary-btn: radial-gradient(ellipse at 50% 0%, oklch(from var(--rj-primary-src) calc(l + 0.12) c h) 0%, var(--rj-primary) 70%);
--rj-primary-btn-hover: radial-gradient(ellipse at 50% 0%, oklch(from var(--rj-primary-src) calc(l + 0.18) c h) 0%, var(--rj-primary) 70%);
/* Hover colours from the effective primary (light or dark mode): lighter and a touch
more saturated, with an extra step for very dark primaries so the change stays visible */
--rj-hover-lift: oklch(from var(--rj-primary) min(calc(l + 0.045 + max(0, 0.3 - l) * 0.25), 0.95) calc(c * 1.16) h);
--rj-hover-settle: oklch(from var(--rj-primary) min(calc(l + 0.03 + max(0, 0.3 - l) * 0.15), 0.93) calc(c * 1.08) h);
--rj-hover-tint: color-mix(in oklab, var(--rj-primary) 16%, var(--rj-bg-elevated));
--rj-hover-tint-settle: color-mix(in oklab, var(--rj-primary) 9%, var(--rj-bg-elevated));
--rj-border-focus: var(--rj-primary);
--rj-focus-ring: var(--rj-primary-muted);
/* Text on the primary colour: near-white on dark primaries, near-black
on light ones (lightness above ~0.68, e.g. orange or yellow). The
server no longer darkens light base colours; this keeps them readable. */
--rj-text-on-primary: oklch(from var(--rj-primary) clamp(0.17, (0.68 - l) * 100, 0.985) 0 0);
--rj-brand: oklch(from var(--rj-accent-base) l c h);
--rj-brand-light: oklch(from var(--rj-accent-base) calc(l + 0.12) c h);
--rj-brand-dark: oklch(from var(--rj-accent-base) calc(l - 0.10) c h);
--rj-brand-darker: oklch(from var(--rj-accent-base) calc(l - 0.18) c h);
--rj-brand-subtle: oklch(from var(--rj-accent-base) l c h / 0.12);
--rj-danger: oklch(from var(--rj-danger-base) l c h);
--rj-danger-hover: oklch(from var(--rj-danger-base) calc(l - 0.08) c h);
--rj-danger-subtle: oklch(from var(--rj-danger-base) l c h / 0.10);
--rj-danger-btn: radial-gradient(ellipse at 50% 0%, oklch(from var(--rj-danger-base) calc(l + 0.10) c h) 0%, var(--rj-danger) 70%);
--rj-danger-btn-hover: radial-gradient(ellipse at 50% 0%, oklch(from var(--rj-danger-base) calc(l + 0.16) c h) 0%, var(--rj-danger) 70%);
--rj-warning: oklch(from var(--rj-warning-base) l c h);
--rj-warning-subtle: oklch(from var(--rj-warning-base) l c h / 0.12);
--rj-warning-text: oklch(from var(--rj-warning-base) min(calc(l - 0.18), 0.48) calc(c * 0.9) h);
--rj-warning-text-strong: oklch(from var(--rj-warning-base) min(calc(l - 0.28), 0.40) calc(c * 0.9) h);
--rj-success: oklch(from var(--rj-success-base) l c h);
--rj-success-subtle: oklch(from var(--rj-success-base) l c h / 0.10);
}
/* --- Interactive colour, every preset, dark: never darker than l 0.72 --- */
[data-site-theme="dark"] {
--rj-primary: oklch(from var(--rj-primary-src) max(l, 0.72) c h);
--rj-primary-hover: oklch(from var(--rj-primary-src) calc(max(l, 0.72) + 0.06) c h);
--rj-primary-active: oklch(from var(--rj-primary-src) calc(max(l, 0.72) - 0.08) c h);
--rj-primary-subtle: oklch(from var(--rj-primary-src) max(l, 0.72) c h / 0.14);
--rj-primary-muted: oklch(from var(--rj-primary-src) max(l, 0.72) c h / 0.24);
--rj-primary-medium: oklch(from var(--rj-primary-src) max(l, 0.72) c h / 0.40);
--rj-primary-btn: radial-gradient(ellipse at 50% 0%, oklch(from var(--rj-primary-src) calc(max(l, 0.72) + 0.10) c h) 0%, var(--rj-primary) 70%);
--rj-primary-btn-hover: radial-gradient(ellipse at 50% 0%, oklch(from var(--rj-primary-src) calc(max(l, 0.72) + 0.16) c h) 0%, var(--rj-primary) 70%);
--rj-brand: oklch(from var(--rj-accent-base) max(l, 0.72) c h);
--rj-brand-light: oklch(from var(--rj-accent-base) calc(max(l, 0.72) + 0.10) c h);
--rj-brand-dark: oklch(from var(--rj-accent-base) calc(max(l, 0.72) - 0.10) c h);
--rj-brand-subtle: oklch(from var(--rj-accent-base) max(l, 0.72) c h / 0.18);
--rj-text-muted: #a1a5ad;
/* The lifted primary is light, so text on it has to be dark to stay readable */
--rj-text-on-primary: #11141b;
--rj-danger: oklch(from var(--rj-danger-base) max(l, 0.68) c h);
--rj-danger-hover: oklch(from var(--rj-danger-base) calc(max(l, 0.68) + 0.06) c h);
--rj-danger-subtle: oklch(from var(--rj-danger-base) max(l, 0.68) c h / 0.16);
--rj-danger-btn: radial-gradient(ellipse at 50% 0%, oklch(from var(--rj-danger-base) calc(max(l, 0.68) + 0.10) c h) 0%, var(--rj-danger) 70%);
--rj-danger-btn-hover: radial-gradient(ellipse at 50% 0%, oklch(from var(--rj-danger-base) calc(max(l, 0.68) + 0.16) c h) 0%, var(--rj-danger) 70%);
--rj-warning: oklch(from var(--rj-warning-base) max(l, 0.72) c h);
--rj-warning-subtle: oklch(from var(--rj-warning-base) max(l, 0.72) c h / 0.14);
--rj-warning-text: oklch(from var(--rj-warning-base) max(l, 0.80) c h);
--rj-warning-text-strong: oklch(from var(--rj-warning-base) max(l, 0.87) calc(c * 0.8) h);
--rj-success: oklch(from var(--rj-success-base) max(l, 0.72) c h);
--rj-success-subtle: oklch(from var(--rj-success-base) max(l, 0.72) c h / 0.16);
}
/* ---------- SOFT (default): shadcn/ui measures on a faintly tinted shell ----------
Reference: shadcn/ui "zinc" theme and its dashboard blocks. Controls h-9
(36px) / h-8 (32px), radius 0.5rem for cards and 6px for controls,
border zinc-200, muted text zinc-500, table heads 40px in muted text.
The shell keeps a whisper of the base colour so Soft stays Soft. */
:root,
[data-theme-preset="soft"] {
/* Soft keeps the hue but caps saturation, so even a loud brand colour sits quietly */
--rj-primary-src: oklch(from var(--rj-base) l min(c, 0.15) h);
--rj-sidebar-bg: oklch(from var(--rj-base) 0.965 min(c, 0.012) h); /* ~zinc-50 */
--rj-bg: oklch(from var(--rj-base) 0.985 min(c, 0.006) h);
--rj-bg-elevated: #ffffff;
--rj-bg-sunken: oklch(from var(--rj-base) 0.955 min(c, 0.012) h); /* ~zinc-100 */
--rj-bg-hover: oklch(from var(--rj-base) 0.975 min(c, 0.008) h); /* muted/50 */
--rj-border: oklch(from var(--rj-base) 0.92 min(c, 0.008) h); /* zinc-200 #e4e4e7 */
--rj-border-strong: oklch(from var(--rj-base) 0.87 min(c, 0.01) h); /* zinc-300 #d4d4d8 */
--rj-text: #09090b; /* zinc-950 */
--rj-text-secondary: #3f3f46; /* zinc-700 */
--rj-text-muted: #71717a; /* zinc-500 */
--rj-sidebar-text: #3f3f46;
--rj-sidebar-text-active: #18181b;
--rj-sidebar-hover-bg: oklch(from var(--rj-base) 0.94 min(c, 0.014) h); /* sidebar-accent */
--rj-sidebar-active-bg: oklch(from var(--rj-base) 0.915 min(c, 0.02) h);
--rj-topbar-bg: var(--rj-sidebar-bg);
--rj-topbar-text: var(--rj-text);
--rj-topbar-text-muted: #52525b;
--rj-topbar-border: transparent;
--rj-radius-sm: 4px;
--rj-radius-md: 6px;
--rj-radius-lg: 8px;
--rj-radius-xl: 12px;
--rj-control-h: calc(2rem * var(--rj-d, 1) + 0.25rem); /* 36px, h-9 */
--rj-control-h-sm: calc(1.75rem * var(--rj-d, 1) + 0.25rem); /* 32px, h-8 */
--rj-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
}
[data-site-theme="dark"],
[data-theme-preset="soft"][data-site-theme="dark"] {
--rj-sidebar-bg: oklch(from var(--rj-base) 0.20 min(c, 0.012) h); /* ~zinc-900 */
--rj-bg: oklch(from var(--rj-base) 0.17 min(c, 0.008) h); /* ~zinc-950 lifted */
--rj-bg-elevated: oklch(from var(--rj-base) 0.215 min(c, 0.01) h);
--rj-bg-sunken: oklch(from var(--rj-base) 0.145 min(c, 0.008) h);
--rj-bg-hover: oklch(from var(--rj-base) 0.255 min(c, 0.01) h);
--rj-border: oklch(from var(--rj-base) 0.30 min(c, 0.012) h); /* zinc-800 #27272a */
--rj-border-strong: oklch(from var(--rj-base) 0.40 min(c, 0.014) h); /* zinc-700 */
--rj-text: #fafafa;
--rj-text-secondary: #d4d4d8; /* zinc-300 */
--rj-text-muted: #a1a1aa; /* zinc-400 */
--rj-sidebar-text: #d4d4d8;
--rj-sidebar-text-active: #fafafa;
--rj-sidebar-hover-bg: oklch(from var(--rj-base) 0.26 min(c, 0.014) h);
--rj-sidebar-active-bg: oklch(from var(--rj-base) 0.30 min(c, 0.02) h);
--rj-topbar-bg: var(--rj-sidebar-bg);
--rj-topbar-text: #fafafa;
--rj-topbar-text-muted: #a1a1aa;
--rj-topbar-border: transparent;
}
/* ---------- CLASSIC: WordPress-like dark chrome, light stage, flat and square ---------- */
[data-theme-preset="classic"] {
--rj-primary-src: var(--rj-base);
--rj-sidebar-bg: #1d2327;
--rj-bg: #f0f0f1;
--rj-bg-elevated: #ffffff;
--rj-bg-sunken: #e6e7e8;
--rj-bg-hover: #f6f7f7;
--rj-border: #c3c4c7;
--rj-border-strong: #8c8f94;
--rj-border-subtle: #dcdcde;
--rj-text: #1d2327;
--rj-text-secondary: #3c434a;
--rj-text-muted: #646970;
--rj-sidebar-text: #f0f0f1;
--rj-sidebar-text-active: var(--rj-text-on-primary);
--rj-sidebar-text-hover: #ffffff;
--rj-sidebar-hover-bg: rgba(255, 255, 255, 0.08);
--rj-sidebar-active-bg: var(--rj-primary);
--rj-sidebar-border: rgba(255, 255, 255, 0.08);
--rj-topbar-bg: #1d2327;
--rj-topbar-text: #f0f0f1;
--rj-topbar-text-muted: #c3c4c7;
--rj-topbar-border: transparent;
--rj-radius-sm: 3px;
--rj-radius-md: 4px;
--rj-radius-lg: 6px;
--rj-radius-xl: 8px;
--rj-shadow-sm: 0 1px 1px rgba(0, 0, 0, 0.04);
}
[data-theme-preset="classic"][data-site-theme="dark"] {
--rj-sidebar-bg: #0e1113;
--rj-bg: #15181b;
--rj-bg-elevated: #1e2327;
--rj-bg-sunken: #101316;
--rj-bg-hover: #262c31;
--rj-border: #3a4248;
--rj-border-strong: #4f5962;
--rj-border-subtle: #2b3238;
--rj-text: #e9ecef;
--rj-text-secondary: #c4cacf;
--rj-text-muted: #9aa2aa;
--rj-sidebar-hover-bg: rgba(255, 255, 255, 0.07);
--rj-topbar-bg: #0e1113;
--rj-topbar-text: #e9ecef;
--rj-topbar-text-muted: #9aa2aa;
}
/* ---------- PAPER: white, hairlines instead of tints, light sidebar ---------- */
[data-theme-preset="paper"] {
--rj-primary-src: var(--rj-base);
--rj-sidebar-bg: #fafaf8;
--rj-bg: #ffffff;
--rj-bg-elevated: #ffffff;
--rj-bg-sunken: #f4f4f1;
--rj-bg-hover: #f6f6f3;
--rj-border: #e3e3df;
--rj-border-strong: #c9c9c3;
--rj-border-subtle: #ececea;
--rj-text: #171717;
--rj-text-secondary: #4b4b4b;
--rj-text-muted: #6f6f6f;
--rj-sidebar-text: #333333;
--rj-sidebar-text-active: var(--rj-text);
--rj-sidebar-hover-bg: rgba(0, 0, 0, 0.045);
--rj-sidebar-active-bg: rgba(0, 0, 0, 0.035);
--rj-sidebar-border: #e3e3df;
--rj-topbar-bg: #ffffff;
--rj-topbar-text: #171717;
--rj-topbar-text-muted: #6f6f6f;
--rj-topbar-border: #e3e3df;
--rj-radius-sm: 4px;
--rj-radius-md: 6px;
--rj-radius-lg: 8px;
--rj-radius-xl: 12px;
--rj-shadow-sm: none;
--rj-shadow-md: 0 2px 10px rgba(0, 0, 0, 0.06);
}
[data-theme-preset="paper"][data-site-theme="dark"] {
--rj-sidebar-bg: #0d0d0d;
--rj-bg: #121212;
--rj-bg-elevated: #181818;
--rj-bg-sunken: #0f0f0f;
--rj-bg-hover: #1e1e1e;
--rj-border: #2c2c2c;
--rj-border-strong: #3f3f3f;
--rj-border-subtle: #222222;
--rj-text: #ededed;
--rj-text-secondary: #c8c8c8;
--rj-text-muted: #9d9d9d;
--rj-sidebar-text: #d0d0d0;
--rj-sidebar-text-active: #ffffff;
--rj-sidebar-hover-bg: rgba(255, 255, 255, 0.06);
--rj-sidebar-active-bg: rgba(255, 255, 255, 0.05);
--rj-sidebar-border: #2c2c2c;
--rj-topbar-bg: #0d0d0d;
--rj-topbar-text: #ededed;
--rj-topbar-text-muted: #9d9d9d;
--rj-topbar-border: #2c2c2c;
}
/* ---------- STUDIO: Vercel / Geist. Monochrome, hairlines, black buttons ----------
Reference: the Vercel dashboard and the Geist design system. Pure neutral
greys (#fafafa stage, #ffffff cards, #eaeaea borders), text #171717 /
#666666, buttons black on white (white on black in dark mode), radius
6px, controls 40px / 32px. The base colour is an accent only: focus
ring, links, active markers, success. */
[data-theme-preset="studio"] {
--rj-primary-src: var(--rj-base);
--rj-primary: #171717;
--rj-primary-hover: #383838;
--rj-primary-active: #000000;
--rj-primary-subtle: rgba(0, 0, 0, 0.05);
--rj-primary-muted: rgba(0, 0, 0, 0.10);
--rj-primary-medium: rgba(0, 0, 0, 0.20);
--rj-primary-btn: var(--rj-primary);
--rj-primary-btn-hover: var(--rj-primary-hover);
--rj-primary-sheen: none;
--rj-text-on-primary: #ffffff;
--rj-border-focus: oklch(from var(--rj-base) l c h);
--rj-focus-ring: oklch(from var(--rj-base) l c h / 0.35);
--rj-success-base: var(--rj-accent-base);
--rj-sidebar-bg: #fafafa;
--rj-bg: #fafafa;
--rj-bg-elevated: #ffffff;
--rj-bg-sunken: #f2f2f2;
--rj-bg-hover: #f5f5f5;
--rj-border: #eaeaea;
--rj-border-strong: #cfcfcf;
--rj-border-subtle: #f2f2f2;
--rj-text: #171717;
--rj-text-secondary: #444444;
--rj-text-muted: #666666;
--rj-sidebar-text: #666666;
--rj-sidebar-text-active: #171717;
--rj-sidebar-hover-bg: rgba(0, 0, 0, 0.04);
--rj-sidebar-active-bg: rgba(0, 0, 0, 0.06);
--rj-sidebar-border: #eaeaea;
--rj-topbar-bg: #ffffff;
--rj-topbar-text: #171717;
--rj-topbar-text-muted: #666666;
--rj-topbar-border: #eaeaea;
--rj-surface-group: #fafafa;
--rj-radius-sm: 4px;
--rj-radius-md: 6px;
--rj-radius-lg: 8px;
--rj-radius-xl: 12px;
--rj-control-h: calc(2.25rem * var(--rj-d, 1) + 0.25rem); /* 40px */
--rj-control-h-sm: calc(1.75rem * var(--rj-d, 1) + 0.25rem); /* 32px */
--rj-shadow-sm: none;
--rj-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
--rj-shadow-lg: 0 8px 30px rgba(0, 0, 0, 0.12);
}
[data-theme-preset="studio"][data-site-theme="dark"] {
--rj-primary: #ededed;
--rj-primary-hover: #cccccc;
--rj-primary-active: #ffffff;
--rj-primary-subtle: rgba(255, 255, 255, 0.06);
--rj-primary-muted: rgba(255, 255, 255, 0.12);
--rj-primary-medium: rgba(255, 255, 255, 0.22);
--rj-primary-btn: var(--rj-primary);
--rj-primary-btn-hover: var(--rj-primary-hover);
--rj-primary-sheen: none;
--rj-text-on-primary: #0a0a0a;
--rj-border-focus: oklch(from var(--rj-base) max(l, 0.72) c h);
--rj-focus-ring: oklch(from var(--rj-base) max(l, 0.72) c h / 0.40);
--rj-sidebar-bg: #000000;
--rj-bg: #000000;
--rj-bg-elevated: #0a0a0a;
--rj-bg-sunken: #000000;
--rj-bg-hover: #141414;
--rj-border: #262626;
--rj-border-strong: #3d3d3d;
--rj-border-subtle: #1a1a1a;
--rj-text: #ededed;
--rj-text-secondary: #c2c2c2;
--rj-text-muted: #a1a1a1;
--rj-sidebar-text: #a1a1a1;
--rj-sidebar-text-active: #ededed;
--rj-sidebar-hover-bg: rgba(255, 255, 255, 0.06);
--rj-sidebar-active-bg: rgba(255, 255, 255, 0.09);
--rj-sidebar-border: #262626;
--rj-topbar-bg: #000000;
--rj-topbar-text: #ededed;
--rj-topbar-text-muted: #a1a1a1;
--rj-topbar-border: #262626;
--rj-surface-group: #0a0a0a;
--rj-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5);
--rj-shadow-lg: 0 8px 30px rgba(0, 0, 0, 0.6);
}
/* ---------- CONSOLE: ops-console look. Monospace, caps, hairlines, one strong accent ----------
Dark first: near-black surfaces, dashed group dividers, square corners,
the base colour at full chroma for everything that means "live" or
"selected". Light mode is the same drawing on grey paper. The preset
pairs with the Geist Mono face on the regular type scale. */
[data-theme-preset="console"] {
--rj-primary-src: var(--rj-base);
--rj-primary-btn: var(--rj-primary);
--rj-primary-btn-hover: var(--rj-primary-hover);
--rj-primary-sheen: none;
--rj-sidebar-bg: #f1f1f1;
--rj-bg: #f1f1f1;
--rj-bg-elevated: #fafafa;
--rj-bg-sunken: #e8e8e8;
--rj-bg-hover: #ececec;
--rj-border: #d2d2d2;
--rj-border-strong: #9a9a9a;
--rj-border-subtle: #e2e2e2;
--rj-text: #111111;
--rj-text-secondary: #3d3d3d;
--rj-text-muted: #5f5f5f;
--rj-sidebar-text: #5f5f5f;
--rj-sidebar-text-active: #111111;
--rj-sidebar-hover-bg: rgba(0, 0, 0, 0.05);
--rj-sidebar-active-bg: rgba(0, 0, 0, 0.07);
--rj-sidebar-border: #d2d2d2;
--rj-topbar-bg: #fafafa;
--rj-topbar-text: #111111;
--rj-topbar-text-muted: #5f5f5f;
--rj-topbar-border: #d2d2d2;
/* Cards on the stage (backup, forms) sit on the card surface, one step above the stage */
--rj-surface-group: #fafafa;
--rj-divider-style: dashed;
--rj-radius-sm: 0px;
--rj-radius-md: 2px;
--rj-radius-lg: 2px;
--rj-radius-xl: 2px;
--rj-control-h: calc(2rem * var(--rj-d, 1) + 0.25rem); /* 36px */
--rj-control-h-sm: calc(1.625rem * var(--rj-d, 1) + 0.25rem); /* 30px */
--rj-shadow-sm: none;
--rj-shadow-md: 0 4px 16px rgba(0, 0, 0, 0.12);
--rj-shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.18);
}
[data-theme-preset="console"][data-site-theme="dark"] {
--rj-sidebar-bg: #0a0a0a;
--rj-bg: #0a0a0a;
--rj-bg-elevated: #121212;
--rj-bg-sunken: #050505;
--rj-bg-hover: #1a1a1a;
--rj-border: #2a2a2a;
--rj-border-strong: #4a4a4a;
--rj-border-subtle: #1f1f1f;
--rj-text: #e8e8e8;
--rj-text-secondary: #bdbdbd;
--rj-text-muted: #8c8c8c;
--rj-sidebar-text: #9a9a9a;
--rj-sidebar-text-active: #f2f2f2;
--rj-sidebar-hover-bg: rgba(255, 255, 255, 0.06);
--rj-sidebar-active-bg: rgba(255, 255, 255, 0.08);
--rj-sidebar-border: #2a2a2a;
--rj-topbar-bg: #0a0a0a;
--rj-topbar-text: #e8e8e8;
--rj-topbar-text-muted: #8c8c8c;
--rj-topbar-border: #2a2a2a;
--rj-surface-group: #121212;
--rj-shadow-md: 0 4px 16px rgba(0, 0, 0, 0.6);
--rj-shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.7);
}
/* ---------- POP: playful dashboard. Dark gradient chrome, light stage, colourful pills ----------
The sidebar and topbar take a deep slate drawn from the base hue and run
as a vertical gradient; the stage is a cool light sheet with rounded
white cards and soft shadows. Labels, legends and panel titles sit in
pill-shaped chips in the primary and semantic colours. The preset pairs
with Atkinson Hyperlegible Next and brings its own four-colour palette. */
[data-theme-preset="pop"] {
--rj-primary-src: var(--rj-base);
/* Chrome: deep slate from the base hue; the gradient runs from the sidebar colour
to a lighter step of it, so a custom sidebar colour keeps the gradient */
--rj-sidebar-bg: oklch(from var(--rj-base) 0.33 min(c, 0.045) h);
--rj-sidebar-gradient: linear-gradient(180deg, var(--rj-sidebar-bg) 0%, oklch(from var(--rj-sidebar-bg) calc(l + 0.09) calc(c * 1.1) h) 100%);
--rj-bg: oklch(from var(--rj-base) 0.955 min(c, 0.014) h);
--rj-bg-elevated: #ffffff;
--rj-bg-sunken: oklch(from var(--rj-base) 0.93 min(c, 0.016) h);
--rj-bg-hover: oklch(from var(--rj-base) 0.965 min(c, 0.012) h);
--rj-border: oklch(from var(--rj-base) 0.90 min(c, 0.02) h);
--rj-border-strong: oklch(from var(--rj-base) 0.78 min(c, 0.03) h);
--rj-border-subtle: oklch(from var(--rj-base) 0.935 min(c, 0.014) h);
--rj-text: oklch(from var(--rj-base) 0.25 min(c, 0.03) h);
--rj-text-secondary: oklch(from var(--rj-base) 0.38 min(c, 0.03) h);
--rj-text-muted: oklch(from var(--rj-base) 0.50 min(c, 0.03) h);
--rj-sidebar-text: oklch(from var(--rj-base) 0.88 min(c, 0.02) h);
--rj-sidebar-text-active: var(--rj-text-on-primary);
--rj-sidebar-text-hover: #ffffff;
--rj-sidebar-hover-bg: rgba(255, 255, 255, 0.09);
--rj-sidebar-active-bg: var(--rj-primary);
--rj-sidebar-border: rgba(255, 255, 255, 0.10);
--rj-topbar-bg: var(--rj-sidebar-bg);
--rj-topbar-text: #ffffff;
--rj-topbar-text-muted: oklch(from var(--rj-base) 0.82 min(c, 0.02) h);
--rj-topbar-border: transparent;
--rj-topbar-divider: rgba(255, 255, 255, 0.14);
/* Cards on the stage are white sheets; grouped surfaces a shade below */
--rj-surface-item: #ffffff;
--rj-surface-group: oklch(from var(--rj-base) 0.975 min(c, 0.008) h);
--rj-radius-sm: 6px;
--rj-radius-md: 10px;
--rj-radius-lg: 30px;
--rj-radius-xl: 30px;
--rj-shadow-sm: 0 1px 2px oklch(from var(--rj-sidebar-bg) l c h / 0.06), 0 3px 10px oklch(from var(--rj-sidebar-bg) l c h / 0.07);
--rj-shadow-md: 0 4px 14px oklch(from var(--rj-sidebar-bg) l c h / 0.12), 0 2px 4px oklch(from var(--rj-sidebar-bg) l c h / 0.06);
--rj-shadow-lg: 0 12px 32px oklch(from var(--rj-sidebar-bg) l c h / 0.18);
--rj-shadow-xl: 0 20px 56px oklch(from var(--rj-sidebar-bg) l c h / 0.26);
}
[data-theme-preset="pop"][data-site-theme="dark"] {
--rj-sidebar-bg: oklch(from var(--rj-base) 0.21 min(c, 0.035) h);
--rj-sidebar-gradient: linear-gradient(180deg, var(--rj-sidebar-bg) 0%, oklch(from var(--rj-sidebar-bg) calc(l + 0.07) calc(c * 1.1) h) 100%);
--rj-bg: oklch(from var(--rj-base) 0.26 min(c, 0.03) h);
--rj-bg-elevated: oklch(from var(--rj-base) 0.31 min(c, 0.03) h);
--rj-bg-sunken: oklch(from var(--rj-base) 0.23 min(c, 0.03) h);
--rj-bg-hover: oklch(from var(--rj-base) 0.34 min(c, 0.03) h);
--rj-border: oklch(from var(--rj-base) 0.38 min(c, 0.03) h);
--rj-border-strong: oklch(from var(--rj-base) 0.48 min(c, 0.03) h);
--rj-border-subtle: oklch(from var(--rj-base) 0.34 min(c, 0.03) h);
--rj-text: oklch(from var(--rj-base) 0.94 min(c, 0.01) h);
--rj-text-secondary: oklch(from var(--rj-base) 0.82 min(c, 0.015) h);
--rj-text-muted: oklch(from var(--rj-base) 0.70 min(c, 0.02) h);
--rj-sidebar-text: oklch(from var(--rj-base) 0.84 min(c, 0.02) h);
--rj-sidebar-hover-bg: rgba(255, 255, 255, 0.08);
--rj-topbar-bg: var(--rj-sidebar-bg);
--rj-topbar-text-muted: oklch(from var(--rj-base) 0.74 min(c, 0.02) h);
--rj-surface-item: var(--rj-bg-elevated);
--rj-surface-group: oklch(from var(--rj-base) 0.29 min(c, 0.03) h);
--rj-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.25), 0 3px 10px rgba(0, 0, 0, 0.22);
--rj-shadow-md: 0 4px 14px rgba(0, 0, 0, 0.35);
--rj-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.45);
--rj-shadow-xl: 0 20px 56px rgba(0, 0, 0, 0.55);
}
}
/* ============================================================
FONTS — local files only (admin/fonts.css declares the faces)
============================================================ */
/* Text size steps: the type scale only, spacing and controls keep their size */
[data-font-size="small"] { --rj-font-scale: 0.92; }
[data-font-size="large"] { --rj-font-scale: 1.1; }
[data-font="plex"] {
--rj-font-sans: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
[data-font="atkinson"] {
--rj-font-sans: 'Atkinson Hyperlegible Next', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
[data-font="public"] {
--rj-font-sans: 'Public Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
[data-font="inter"] {
--rj-font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
[data-font="geist-mono"] {
--rj-font-sans: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
--rj-font-mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}
/* ============================================================
ADMIN BAR — always dark, scoped tokens
============================================================ */
#admin-bar,
.rj-adminbar {
--rj-bar-bg: rgba(20, 20, 20, 0.92);
--rj-bar-bg-solid: #141414;
--rj-bar-border: #2a2a2a;
--rj-bar-text: #e5e5e5;
--rj-bar-text-muted: #888888;
--rj-bar-hover: #222222;
--rj-bar-accent: #b45309;
}