diff --git a/client/index.html b/client/index.html index 3467bc698..aeb6517ce 100644 --- a/client/index.html +++ b/client/index.html @@ -10,6 +10,7 @@ + BookOrbit diff --git a/client/public/theme-init.js b/client/public/theme-init.js index 7b60aa368..d52260175 100644 --- a/client/public/theme-init.js +++ b/client/public/theme-init.js @@ -2,19 +2,42 @@ function readStoredValue(key, fallback) { var stored = localStorage.getItem(key) if (stored === null) return fallback + var value = stored try { - return JSON.parse(stored) + value = JSON.parse(stored) } catch { - return stored + value = stored } + return typeof value === 'string' ? value : fallback } + // Mirrors STANDALONE_ROUTE_PREFIXES in src/lib/theme-styles.ts; theme-init.spec.ts keeps them equal. + var STANDALONE_ROUTE_PREFIXES = ['/read/', '/login', '/register', '/setup', '/forgot-password', '/reset-password', '/oauth2-callback', '/magic'] + + function isAppShellPath(path) { + for (var i = 0; i < STANDALONE_ROUTE_PREFIXES.length; i++) { + var prefix = STANDALONE_ROUTE_PREFIXES[i] + if (path === prefix || path.indexOf(prefix.charAt(prefix.length - 1) === '/' ? prefix : prefix + '/') === 0) return false + } + return true + } + + var root = document.documentElement var theme = readStoredValue('theme', 'system') - var accent = readStoredValue('accent', 'neutral') + var accent = readStoredValue('accent', 'blue') var radius = readStoredValue('radius', 'default') + var style = readStoredValue('style', 'bookorbit') + var surfacePalette = readStoredValue('surfacePalette', 'steel') + var rawReach = localStorage.getItem('glowReach') + var storedReach = rawReach === null ? 80 : Number(rawReach) + var glowReach = isFinite(storedReach) ? Math.min(200, Math.max(0, storedReach)) : 80 var systemDark = typeof window.matchMedia === 'function' && window.matchMedia('(prefers-color-scheme: dark)').matches var isDark = theme === 'dark' || (theme !== 'light' && systemDark) - if (isDark) document.documentElement.classList.add('dark') - if (accent !== 'neutral') document.documentElement.classList.add('accent-' + accent) - if (radius !== 'default') document.documentElement.classList.add('radius-' + radius) + if (isDark) root.classList.add('dark') + root.classList.add('accent-' + accent) + if (radius !== 'default') root.classList.add('radius-' + radius) + root.setAttribute('data-style', isAppShellPath(window.location.pathname) ? style : 'bookorbit') + root.setAttribute('data-surface', surfacePalette) + root.style.setProperty('--glow-reach', String(glowReach / 100)) + root.setAttribute('data-glow', glowReach > 0 ? 'on' : 'off') })() diff --git a/client/public/topbar.png b/client/public/topbar.png deleted file mode 100644 index 6fb203c3b..000000000 Binary files a/client/public/topbar.png and /dev/null differ diff --git a/client/src/App.vue b/client/src/App.vue index 708dd650f..1afbd619a 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -4,8 +4,8 @@ import { useRoute } from 'vue-router' import { INIT_OPTIONS_KEY, THEME_KEY } from 'vue-echarts' import { APP_FEATURES } from '@bookorbit/types' import { useChangePasswordDialog } from '@/composables/useChangePasswordDialog' -import { useThemeStore } from '@/stores/theme' -import { getBookorbitThemeName, initChartThemes } from '@/lib/echarts' +import { useChartTokens } from '@/composables/useChartTokens' +import { buildChartTheme } from '@/lib/echarts' import ChangePasswordDialog from '@/features/auth/ChangePasswordDialog.vue' import WhatsNewDialog from '@/features/whats-new/WhatsNewDialog.vue' import { useWhatsNew } from '@/features/whats-new/composables/useWhatsNew' @@ -40,7 +40,7 @@ const TOASTER_MOBILE_OFFSET = { } const { isOpen } = useChangePasswordDialog() -const themeStore = useThemeStore() +const chartTokens = useChartTokens() const route = useRoute() const { user } = useAuth() @@ -79,12 +79,10 @@ watch( (name) => syncPopup(name as string | undefined), ) -initChartThemes() - provide(INIT_OPTIONS_KEY, { renderer: 'svg' }) provide( THEME_KEY, - computed(() => getBookorbitThemeName(themeStore.resolvedTheme, themeStore.accent)), + computed(() => buildChartTheme(chartTokens.value)), ) diff --git a/client/src/assets/main.css b/client/src/assets/main.css index e8538a074..b3c4d4e97 100644 --- a/client/src/assets/main.css +++ b/client/src/assets/main.css @@ -6,6 +6,8 @@ @import './theme/tokens.css'; @import './theme/accents.css'; @import './theme/radius.css'; +@import './theme/surfaces.css'; +@import './theme/styles/nostalgia.css'; @import './theme/bridge.css'; @import './theme/cover-effects.css'; @@ -252,11 +254,34 @@ } .glow-wrapper { - background-image: radial-gradient(50% 50% at center -25px, color-mix(in oklch, var(--primary) 35%, transparent) 0%, transparent 100%); - background-blend-mode: hard-light, color-dodge; + background-image: var(--glow-image); background-position: top; background-repeat: no-repeat; - background-size: auto 12rem; + background-size: auto calc(var(--glow-band) * var(--glow-reach)); +} + +/* The texture sits on its own layer so its tiles keep their size; the reach only moves the fade. Negative + z-index keeps it under the shell's content and the glow, like the background patterns. */ +.glow-wrapper::after { + content: ''; + position: absolute; + inset: 0 0 auto; + z-index: -1; + height: calc(var(--glow-band) * var(--glow-reach)); + pointer-events: none; + background-image: var(--glow-texture); + background-position: top center; + background-size: var(--glow-texture-size); + -webkit-mask-image: radial-gradient(ellipse 62% 100% at 50% 0%, #000 0%, transparent 100%); + mask-image: radial-gradient(ellipse 62% 100% at 50% 0%, #000 0%, transparent 100%); +} + +html[data-glow='off'] .glow-wrapper { + background-image: none; +} + +html[data-glow='off'] .glow-wrapper::after { + content: none; } @layer base { @@ -358,7 +383,7 @@ @layer components { .viewer-btn { - @apply flex items-center justify-center w-8 h-8 rounded text-foreground hover:bg-muted transition-colors shrink-0 disabled:opacity-30 disabled:cursor-not-allowed; + @apply flex items-center justify-center w-8 h-8 rounded-xs text-foreground hover:bg-muted transition-colors shrink-0 disabled:opacity-30 disabled:cursor-not-allowed; } .viewer-sep { @apply w-px h-5 mx-1 bg-border shrink-0; @@ -385,6 +410,44 @@ .settings-value { @apply text-sm font-medium tabular-nums text-foreground; } + /* ── App shell ───────────────────────────────────────────── + The glass behind the sidebar and header cards. A style swaps + --shell-backdrop to change it. + ────────────────────────────────────────────────────────────── */ + .shell-backdrop { + backdrop-filter: var(--shell-backdrop); + -webkit-backdrop-filter: var(--shell-backdrop); + } + .sidebar-section-label { + font-size: var(--sidebar-heading-size); + font-weight: var(--sidebar-heading-weight); + letter-spacing: var(--sidebar-heading-tracking); + color: var(--sidebar-heading-foreground); + text-transform: uppercase; + } + /* Count chips beside sidebar rows and collapsed sections. Colour utilities on the element still win. */ + .sidebar-count { + background-color: var(--sidebar-count-bg); + font-size: var(--sidebar-count-size); + font-weight: var(--sidebar-count-weight); + color: var(--sidebar-count-foreground); + } + + /* ── Book metadata chips ─────────────────────────────────── + Genres and tags on the book detail page. The ring is inset so + a style can add one without moving the genre fold measurement. + ────────────────────────────────────────────────────────────── */ + .chip-genre { + background-color: var(--chip-genre-bg); + color: var(--chip-genre-fg); + box-shadow: inset 0 0 0 1px var(--chip-genre-border); + } + .chip-tag { + background-color: var(--chip-tag-bg); + color: var(--chip-tag-fg); + border-color: var(--chip-tag-border); + } + /* ── Provider chips ──────────────────────────────────────── Callers set --provider-color; the ink/fill/ring mixes come from the theme so light mode darkens the brand hue enough to pass contrast. See tokens.css. diff --git a/client/src/assets/theme/accents.css b/client/src/assets/theme/accents.css index e59f4ac6f..c7eea518f 100644 --- a/client/src/assets/theme/accents.css +++ b/client/src/assets/theme/accents.css @@ -1,6 +1,7 @@ /* ── Accent presets ────────────────────────────────────────── Applied as a class on . Overrides --tint-h (surfaces) - and --primary (interactive elements). + and --accent-primary, which --primary reads unless a style + derives its own shade from it. Vivid: high chroma. Pastel: low chroma, muted feel. Yellow and yellow-green accents use dark foreground text where needed. ────────────────────────────────────────────────────────────── */ @@ -10,7 +11,7 @@ html.accent-white { --tint-h: 0; --tint-c: 0; - --primary: oklch(0.2 0 0); + --accent-primary: oklch(0.2 0 0); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.2 0 0); --sidebar: oklch(0.985 0 0); @@ -20,7 +21,7 @@ html.accent-white { html.accent-white.dark { --tint-h: 0; --tint-c: 0; - --primary: oklch(0.985 0 0); + --accent-primary: oklch(0.985 0 0); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.985 0 0); --sidebar: oklch(0.205 0 0); @@ -31,7 +32,7 @@ html.accent-white.dark { html.accent-grey { --tint-h: 0; --tint-c: 0; - --primary: oklch(0.55 0 0); + --accent-primary: oklch(0.55 0 0); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.55 0 0); --sidebar: oklch(0.96 0 0); @@ -41,7 +42,7 @@ html.accent-grey { html.accent-grey.dark { --tint-h: 0; --tint-c: 0; - --primary: oklch(0.75 0 0); + --accent-primary: oklch(0.75 0 0); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.75 0 0); --sidebar: oklch(0.22 0 0); @@ -51,14 +52,14 @@ html.accent-grey.dark { html.accent-scarlet { --tint-h: 2; - --primary: oklch(0.58 0.25 2); + --accent-primary: oklch(0.58 0.25 2); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.58 0.25 2); --sidebar-primary: oklch(0.58 0.25 2); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-scarlet.dark { - --primary: oklch(0.74 0.2 2); + --accent-primary: oklch(0.74 0.2 2); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.74 0.2 2); --sidebar-primary: oklch(0.74 0.2 2); @@ -67,14 +68,14 @@ html.accent-scarlet.dark { html.accent-rose { --tint-h: 15; - --primary: oklch(0.57 0.24 15); + --accent-primary: oklch(0.57 0.24 15); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.57 0.24 15); --sidebar-primary: oklch(0.57 0.24 15); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-rose.dark { - --primary: oklch(0.73 0.2 15); + --accent-primary: oklch(0.73 0.2 15); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.73 0.2 15); --sidebar-primary: oklch(0.73 0.2 15); @@ -83,14 +84,14 @@ html.accent-rose.dark { html.accent-orange { --tint-h: 42; - --primary: oklch(0.64 0.22 42); + --accent-primary: oklch(0.64 0.22 42); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.64 0.22 42); --sidebar-primary: oklch(0.64 0.22 42); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-orange.dark { - --primary: oklch(0.78 0.18 42); + --accent-primary: oklch(0.78 0.18 42); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.78 0.18 42); --sidebar-primary: oklch(0.78 0.18 42); @@ -99,14 +100,14 @@ html.accent-orange.dark { html.accent-marigold { --tint-h: 82; - --primary: oklch(0.76 0.18 82); + --accent-primary: oklch(0.76 0.18 82); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.76 0.18 82); --sidebar-primary: oklch(0.76 0.18 82); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-marigold.dark { - --primary: oklch(0.84 0.15 82); + --accent-primary: oklch(0.84 0.15 82); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.84 0.15 82); --sidebar-primary: oklch(0.84 0.15 82); @@ -115,14 +116,14 @@ html.accent-marigold.dark { html.accent-amber { --tint-h: 70; - --primary: oklch(0.72 0.17 70); + --accent-primary: oklch(0.72 0.17 70); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.72 0.17 70); --sidebar-primary: oklch(0.72 0.17 70); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-amber.dark { - --primary: oklch(0.82 0.17 70); + --accent-primary: oklch(0.82 0.17 70); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.82 0.17 70); --sidebar-primary: oklch(0.82 0.17 70); @@ -131,14 +132,14 @@ html.accent-amber.dark { html.accent-yellow { --tint-h: 95; - --primary: oklch(0.75 0.18 95); + --accent-primary: oklch(0.75 0.18 95); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.75 0.18 95); --sidebar-primary: oklch(0.75 0.18 95); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-yellow.dark { - --primary: oklch(0.84 0.16 95); + --accent-primary: oklch(0.84 0.16 95); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.84 0.16 95); --sidebar-primary: oklch(0.84 0.16 95); @@ -147,14 +148,14 @@ html.accent-yellow.dark { html.accent-viridian { --tint-h: 171; - --primary: oklch(0.54 0.17 171); + --accent-primary: oklch(0.54 0.17 171); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.54 0.17 171); --sidebar-primary: oklch(0.54 0.17 171); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-viridian.dark { - --primary: oklch(0.73 0.14 171); + --accent-primary: oklch(0.73 0.14 171); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.73 0.14 171); --sidebar-primary: oklch(0.73 0.14 171); @@ -163,14 +164,14 @@ html.accent-viridian.dark { html.accent-lime { --tint-h: 118; - --primary: oklch(0.64 0.2 118); + --accent-primary: oklch(0.64 0.2 118); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.64 0.2 118); --sidebar-primary: oklch(0.64 0.2 118); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-lime.dark { - --primary: oklch(0.77 0.18 118); + --accent-primary: oklch(0.77 0.18 118); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.77 0.18 118); --sidebar-primary: oklch(0.77 0.18 118); @@ -179,14 +180,14 @@ html.accent-lime.dark { html.accent-green { --tint-h: 142; - --primary: oklch(0.527 0.18 142); + --accent-primary: oklch(0.527 0.18 142); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.527 0.18 142); --sidebar-primary: oklch(0.527 0.18 142); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-green.dark { - --primary: oklch(0.72 0.18 142); + --accent-primary: oklch(0.72 0.18 142); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.72 0.18 142); --sidebar-primary: oklch(0.72 0.18 142); @@ -195,14 +196,14 @@ html.accent-green.dark { html.accent-emerald { --tint-h: 162; - --primary: oklch(0.52 0.17 162); + --accent-primary: oklch(0.52 0.17 162); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.52 0.17 162); --sidebar-primary: oklch(0.52 0.17 162); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-emerald.dark { - --primary: oklch(0.72 0.15 162); + --accent-primary: oklch(0.72 0.15 162); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.72 0.15 162); --sidebar-primary: oklch(0.72 0.15 162); @@ -211,14 +212,14 @@ html.accent-emerald.dark { html.accent-teal { --tint-h: 180; - --primary: oklch(0.52 0.18 180); + --accent-primary: oklch(0.52 0.18 180); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.52 0.18 180); --sidebar-primary: oklch(0.52 0.18 180); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-teal.dark { - --primary: oklch(0.74 0.16 180); + --accent-primary: oklch(0.74 0.16 180); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.74 0.16 180); --sidebar-primary: oklch(0.74 0.16 180); @@ -227,14 +228,14 @@ html.accent-teal.dark { html.accent-cyan { --tint-h: 197; - --primary: oklch(0.52 0.2 197); + --accent-primary: oklch(0.52 0.2 197); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.52 0.2 197); --sidebar-primary: oklch(0.52 0.2 197); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-cyan.dark { - --primary: oklch(0.75 0.17 197); + --accent-primary: oklch(0.75 0.17 197); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.75 0.17 197); --sidebar-primary: oklch(0.75 0.17 197); @@ -243,14 +244,14 @@ html.accent-cyan.dark { html.accent-jade { --tint-h: 155; - --primary: oklch(0.62 0.2 155); + --accent-primary: oklch(0.62 0.2 155); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.62 0.2 155); --sidebar-primary: oklch(0.62 0.2 155); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-jade.dark { - --primary: oklch(0.78 0.17 155); + --accent-primary: oklch(0.78 0.17 155); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.78 0.17 155); --sidebar-primary: oklch(0.78 0.17 155); @@ -259,14 +260,14 @@ html.accent-jade.dark { html.accent-iris { --tint-h: 270; - --primary: oklch(0.52 0.25 270); + --accent-primary: oklch(0.52 0.25 270); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.52 0.25 270); --sidebar-primary: oklch(0.52 0.25 270); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-iris.dark { - --primary: oklch(0.72 0.21 270); + --accent-primary: oklch(0.72 0.21 270); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.72 0.21 270); --sidebar-primary: oklch(0.72 0.21 270); @@ -275,14 +276,14 @@ html.accent-iris.dark { html.accent-blue { --tint-h: 263; - --primary: oklch(0.487 0.25 263); + --accent-primary: oklch(0.487 0.25 263); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.487 0.25 263); --sidebar-primary: oklch(0.487 0.25 263); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-blue.dark { - --primary: oklch(0.72 0.2 263); + --accent-primary: oklch(0.72 0.2 263); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.72 0.2 263); --sidebar-primary: oklch(0.72 0.2 263); @@ -291,14 +292,14 @@ html.accent-blue.dark { html.accent-indigo { --tint-h: 276; - --primary: oklch(0.51 0.26 276); + --accent-primary: oklch(0.51 0.26 276); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.51 0.26 276); --sidebar-primary: oklch(0.51 0.26 276); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-indigo.dark { - --primary: oklch(0.72 0.22 276); + --accent-primary: oklch(0.72 0.22 276); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.72 0.22 276); --sidebar-primary: oklch(0.72 0.22 276); @@ -307,14 +308,14 @@ html.accent-indigo.dark { html.accent-violet { --tint-h: 292; - --primary: oklch(0.491 0.27 292); + --accent-primary: oklch(0.491 0.27 292); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.491 0.27 292); --sidebar-primary: oklch(0.491 0.27 292); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-violet.dark { - --primary: oklch(0.72 0.23 292); + --accent-primary: oklch(0.72 0.23 292); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.72 0.23 292); --sidebar-primary: oklch(0.72 0.23 292); @@ -323,14 +324,14 @@ html.accent-violet.dark { html.accent-fuchsia { --tint-h: 312; - --primary: oklch(0.56 0.27 312); + --accent-primary: oklch(0.56 0.27 312); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.56 0.27 312); --sidebar-primary: oklch(0.56 0.27 312); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-fuchsia.dark { - --primary: oklch(0.75 0.22 312); + --accent-primary: oklch(0.75 0.22 312); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.75 0.22 312); --sidebar-primary: oklch(0.75 0.22 312); @@ -339,14 +340,14 @@ html.accent-fuchsia.dark { html.accent-pink { --tint-h: 328; - --primary: oklch(0.56 0.26 328); + --accent-primary: oklch(0.56 0.26 328); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.56 0.26 328); --sidebar-primary: oklch(0.56 0.26 328); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-pink.dark { - --primary: oklch(0.75 0.22 328); + --accent-primary: oklch(0.75 0.22 328); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.75 0.22 328); --sidebar-primary: oklch(0.75 0.22 328); @@ -357,14 +358,14 @@ html.accent-pink.dark { html.accent-rosewater { --tint-h: 2; - --primary: oklch(0.7 0.125 2); + --accent-primary: oklch(0.7 0.125 2); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.7 0.125 2); --sidebar-primary: oklch(0.7 0.125 2); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-rosewater.dark { - --primary: oklch(0.8 0.11 2); + --accent-primary: oklch(0.8 0.11 2); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.8 0.11 2); --sidebar-primary: oklch(0.8 0.11 2); @@ -373,14 +374,14 @@ html.accent-rosewater.dark { html.accent-coral { --tint-h: 15; - --primary: oklch(0.69 0.12 15); + --accent-primary: oklch(0.69 0.12 15); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.69 0.12 15); --sidebar-primary: oklch(0.69 0.12 15); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-coral.dark { - --primary: oklch(0.79 0.11 15); + --accent-primary: oklch(0.79 0.11 15); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.79 0.11 15); --sidebar-primary: oklch(0.79 0.11 15); @@ -389,14 +390,14 @@ html.accent-coral.dark { html.accent-peach { --tint-h: 42; - --primary: oklch(0.76 0.11 42); + --accent-primary: oklch(0.76 0.11 42); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.76 0.11 42); --sidebar-primary: oklch(0.76 0.11 42); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-peach.dark { - --primary: oklch(0.84 0.1 42); + --accent-primary: oklch(0.84 0.1 42); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.84 0.1 42); --sidebar-primary: oklch(0.84 0.1 42); @@ -405,14 +406,14 @@ html.accent-peach.dark { html.accent-flax { --tint-h: 82; - --primary: oklch(0.82 0.09 82); + --accent-primary: oklch(0.82 0.09 82); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.82 0.09 82); --sidebar-primary: oklch(0.82 0.09 82); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-flax.dark { - --primary: oklch(0.88 0.08 82); + --accent-primary: oklch(0.88 0.08 82); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.88 0.08 82); --sidebar-primary: oklch(0.88 0.08 82); @@ -421,14 +422,14 @@ html.accent-flax.dark { html.accent-butter { --tint-h: 70; - --primary: oklch(0.82 0.085 70); + --accent-primary: oklch(0.82 0.085 70); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.82 0.085 70); --sidebar-primary: oklch(0.82 0.085 70); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-butter.dark { - --primary: oklch(0.88 0.09 70); + --accent-primary: oklch(0.88 0.09 70); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.88 0.09 70); --sidebar-primary: oklch(0.88 0.09 70); @@ -437,14 +438,14 @@ html.accent-butter.dark { html.accent-lemon { --tint-h: 95; - --primary: oklch(0.82 0.09 95); + --accent-primary: oklch(0.82 0.09 95); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.82 0.09 95); --sidebar-primary: oklch(0.82 0.09 95); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-lemon.dark { - --primary: oklch(0.88 0.09 95); + --accent-primary: oklch(0.88 0.09 95); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.88 0.09 95); --sidebar-primary: oklch(0.88 0.09 95); @@ -453,14 +454,14 @@ html.accent-lemon.dark { html.accent-foam { --tint-h: 171; - --primary: oklch(0.68 0.085 171); + --accent-primary: oklch(0.68 0.085 171); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.085 171); --sidebar-primary: oklch(0.68 0.085 171); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-foam.dark { - --primary: oklch(0.79 0.08 171); + --accent-primary: oklch(0.79 0.08 171); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.79 0.08 171); --sidebar-primary: oklch(0.79 0.08 171); @@ -469,14 +470,14 @@ html.accent-foam.dark { html.accent-celadon { --tint-h: 118; - --primary: oklch(0.76 0.1 118); + --accent-primary: oklch(0.76 0.1 118); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.76 0.1 118); --sidebar-primary: oklch(0.76 0.1 118); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-celadon.dark { - --primary: oklch(0.83 0.1 118); + --accent-primary: oklch(0.83 0.1 118); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.83 0.1 118); --sidebar-primary: oklch(0.83 0.1 118); @@ -485,14 +486,14 @@ html.accent-celadon.dark { html.accent-sage { --tint-h: 142; - --primary: oklch(0.68 0.09 142); + --accent-primary: oklch(0.68 0.09 142); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.09 142); --sidebar-primary: oklch(0.68 0.09 142); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-sage.dark { - --primary: oklch(0.78 0.1 142); + --accent-primary: oklch(0.78 0.1 142); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.78 0.1 142); --sidebar-primary: oklch(0.78 0.1 142); @@ -501,14 +502,14 @@ html.accent-sage.dark { html.accent-mint { --tint-h: 162; - --primary: oklch(0.68 0.085 162); + --accent-primary: oklch(0.68 0.085 162); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.085 162); --sidebar-primary: oklch(0.68 0.085 162); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-mint.dark { - --primary: oklch(0.78 0.08 162); + --accent-primary: oklch(0.78 0.08 162); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.78 0.08 162); --sidebar-primary: oklch(0.78 0.08 162); @@ -517,14 +518,14 @@ html.accent-mint.dark { html.accent-seafoam { --tint-h: 180; - --primary: oklch(0.68 0.09 180); + --accent-primary: oklch(0.68 0.09 180); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.09 180); --sidebar-primary: oklch(0.68 0.09 180); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-seafoam.dark { - --primary: oklch(0.8 0.09 180); + --accent-primary: oklch(0.8 0.09 180); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.8 0.09 180); --sidebar-primary: oklch(0.8 0.09 180); @@ -533,14 +534,14 @@ html.accent-seafoam.dark { html.accent-powder { --tint-h: 197; - --primary: oklch(0.68 0.1 197); + --accent-primary: oklch(0.68 0.1 197); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.1 197); --sidebar-primary: oklch(0.68 0.1 197); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-powder.dark { - --primary: oklch(0.81 0.09 197); + --accent-primary: oklch(0.81 0.09 197); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.81 0.09 197); --sidebar-primary: oklch(0.81 0.09 197); @@ -549,14 +550,14 @@ html.accent-powder.dark { html.accent-sea-glass { --tint-h: 155; - --primary: oklch(0.74 0.1 155); + --accent-primary: oklch(0.74 0.1 155); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.74 0.1 155); --sidebar-primary: oklch(0.74 0.1 155); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-sea-glass.dark { - --primary: oklch(0.84 0.09 155); + --accent-primary: oklch(0.84 0.09 155); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.84 0.09 155); --sidebar-primary: oklch(0.84 0.09 155); @@ -565,14 +566,14 @@ html.accent-sea-glass.dark { html.accent-cornflower { --tint-h: 247; - --primary: oklch(0.68 0.14 247); + --accent-primary: oklch(0.68 0.14 247); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.14 247); --sidebar-primary: oklch(0.68 0.14 247); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-cornflower.dark { - --primary: oklch(0.76 0.12 247); + --accent-primary: oklch(0.76 0.12 247); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.76 0.12 247); --sidebar-primary: oklch(0.76 0.12 247); @@ -581,14 +582,14 @@ html.accent-cornflower.dark { html.accent-periwinkle { --tint-h: 263; - --primary: oklch(0.68 0.125 263); + --accent-primary: oklch(0.68 0.125 263); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.125 263); --sidebar-primary: oklch(0.68 0.125 263); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-periwinkle.dark { - --primary: oklch(0.78 0.11 263); + --accent-primary: oklch(0.78 0.11 263); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.78 0.11 263); --sidebar-primary: oklch(0.78 0.11 263); @@ -597,14 +598,14 @@ html.accent-periwinkle.dark { html.accent-wisteria { --tint-h: 276; - --primary: oklch(0.68 0.13 276); + --accent-primary: oklch(0.68 0.13 276); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.13 276); --sidebar-primary: oklch(0.68 0.13 276); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-wisteria.dark { - --primary: oklch(0.78 0.12 276); + --accent-primary: oklch(0.78 0.12 276); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.78 0.12 276); --sidebar-primary: oklch(0.78 0.12 276); @@ -613,14 +614,14 @@ html.accent-wisteria.dark { html.accent-lavender { --tint-h: 292; - --primary: oklch(0.68 0.135 292); + --accent-primary: oklch(0.68 0.135 292); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.135 292); --sidebar-primary: oklch(0.68 0.135 292); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-lavender.dark { - --primary: oklch(0.78 0.13 292); + --accent-primary: oklch(0.78 0.13 292); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.78 0.13 292); --sidebar-primary: oklch(0.78 0.13 292); @@ -629,14 +630,14 @@ html.accent-lavender.dark { html.accent-orchid { --tint-h: 312; - --primary: oklch(0.68 0.135 312); + --accent-primary: oklch(0.68 0.135 312); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.135 312); --sidebar-primary: oklch(0.68 0.135 312); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-orchid.dark { - --primary: oklch(0.81 0.12 312); + --accent-primary: oklch(0.81 0.12 312); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.81 0.12 312); --sidebar-primary: oklch(0.81 0.12 312); @@ -645,14 +646,14 @@ html.accent-orchid.dark { html.accent-blush { --tint-h: 328; - --primary: oklch(0.68 0.13 328); + --accent-primary: oklch(0.68 0.13 328); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.13 328); --sidebar-primary: oklch(0.68 0.13 328); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-blush.dark { - --primary: oklch(0.81 0.12 328); + --accent-primary: oklch(0.81 0.12 328); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.81 0.12 328); --sidebar-primary: oklch(0.81 0.12 328); @@ -661,14 +662,14 @@ html.accent-blush.dark { html.accent-vermilion { --tint-h: 28; - --primary: oklch(0.62 0.24 28); + --accent-primary: oklch(0.62 0.24 28); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.62 0.24 28); --sidebar-primary: oklch(0.62 0.24 28); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-vermilion.dark { - --primary: oklch(0.77 0.19 28); + --accent-primary: oklch(0.77 0.19 28); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.77 0.19 28); --sidebar-primary: oklch(0.77 0.19 28); @@ -677,14 +678,14 @@ html.accent-vermilion.dark { html.accent-salmon { --tint-h: 28; - --primary: oklch(0.74 0.12 28); + --accent-primary: oklch(0.74 0.12 28); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.74 0.12 28); --sidebar-primary: oklch(0.74 0.12 28); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-salmon.dark { - --primary: oklch(0.83 0.1 28); + --accent-primary: oklch(0.83 0.1 28); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.83 0.1 28); --sidebar-primary: oklch(0.83 0.1 28); @@ -693,14 +694,14 @@ html.accent-salmon.dark { html.accent-copper { --tint-h: 56; - --primary: oklch(0.65 0.19 56); + --accent-primary: oklch(0.65 0.19 56); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.65 0.19 56); --sidebar-primary: oklch(0.65 0.19 56); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-copper.dark { - --primary: oklch(0.79 0.16 56); + --accent-primary: oklch(0.79 0.16 56); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.79 0.16 56); --sidebar-primary: oklch(0.79 0.16 56); @@ -709,14 +710,14 @@ html.accent-copper.dark { html.accent-sand { --tint-h: 56; - --primary: oklch(0.77 0.095 56); + --accent-primary: oklch(0.77 0.095 56); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.77 0.095 56); --sidebar-primary: oklch(0.77 0.095 56); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-sand.dark { - --primary: oklch(0.85 0.09 56); + --accent-primary: oklch(0.85 0.09 56); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.85 0.09 56); --sidebar-primary: oklch(0.85 0.09 56); @@ -725,14 +726,14 @@ html.accent-sand.dark { html.accent-chartreuse { --tint-h: 106; - --primary: oklch(0.76 0.2 106); + --accent-primary: oklch(0.76 0.2 106); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.76 0.2 106); --sidebar-primary: oklch(0.76 0.2 106); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-chartreuse.dark { - --primary: oklch(0.83 0.17 106); + --accent-primary: oklch(0.83 0.17 106); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.83 0.17 106); --sidebar-primary: oklch(0.83 0.17 106); @@ -741,14 +742,14 @@ html.accent-chartreuse.dark { html.accent-pear { --tint-h: 106; - --primary: oklch(0.82 0.1 106); + --accent-primary: oklch(0.82 0.1 106); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.82 0.1 106); --sidebar-primary: oklch(0.82 0.1 106); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-pear.dark { - --primary: oklch(0.88 0.09 106); + --accent-primary: oklch(0.88 0.09 106); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.88 0.09 106); --sidebar-primary: oklch(0.88 0.09 106); @@ -757,14 +758,14 @@ html.accent-pear.dark { html.accent-wasabi { --tint-h: 130; - --primary: oklch(0.68 0.19 130); + --accent-primary: oklch(0.68 0.19 130); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.19 130); --sidebar-primary: oklch(0.68 0.19 130); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-wasabi.dark { - --primary: oklch(0.79 0.16 130); + --accent-primary: oklch(0.79 0.16 130); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.79 0.16 130); --sidebar-primary: oklch(0.79 0.16 130); @@ -773,14 +774,14 @@ html.accent-wasabi.dark { html.accent-sprout { --tint-h: 130; - --primary: oklch(0.8 0.095 130); + --accent-primary: oklch(0.8 0.095 130); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.8 0.095 130); --sidebar-primary: oklch(0.8 0.095 130); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-sprout.dark { - --primary: oklch(0.85 0.09 130); + --accent-primary: oklch(0.85 0.09 130); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.85 0.09 130); --sidebar-primary: oklch(0.85 0.09 130); @@ -789,14 +790,14 @@ html.accent-sprout.dark { html.accent-malachite { --tint-h: 152; - --primary: oklch(0.56 0.18 152); + --accent-primary: oklch(0.56 0.18 152); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.56 0.18 152); --sidebar-primary: oklch(0.56 0.18 152); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-malachite.dark { - --primary: oklch(0.73 0.15 152); + --accent-primary: oklch(0.73 0.15 152); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.73 0.15 152); --sidebar-primary: oklch(0.73 0.15 152); @@ -805,14 +806,14 @@ html.accent-malachite.dark { html.accent-aloe { --tint-h: 152; - --primary: oklch(0.68 0.09 152); + --accent-primary: oklch(0.68 0.09 152); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.09 152); --sidebar-primary: oklch(0.68 0.09 152); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-aloe.dark { - --primary: oklch(0.79 0.08 152); + --accent-primary: oklch(0.79 0.08 152); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.79 0.08 152); --sidebar-primary: oklch(0.79 0.08 152); @@ -821,14 +822,14 @@ html.accent-aloe.dark { html.accent-turquoise { --tint-h: 188; - --primary: oklch(0.58 0.18 188); + --accent-primary: oklch(0.58 0.18 188); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.58 0.18 188); --sidebar-primary: oklch(0.58 0.18 188); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-turquoise.dark { - --primary: oklch(0.75 0.15 188); + --accent-primary: oklch(0.75 0.15 188); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.75 0.15 188); --sidebar-primary: oklch(0.75 0.15 188); @@ -837,14 +838,14 @@ html.accent-turquoise.dark { html.accent-aqua { --tint-h: 188; - --primary: oklch(0.7 0.09 188); + --accent-primary: oklch(0.7 0.09 188); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.7 0.09 188); --sidebar-primary: oklch(0.7 0.09 188); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-aqua.dark { - --primary: oklch(0.81 0.08 188); + --accent-primary: oklch(0.81 0.08 188); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.81 0.08 188); --sidebar-primary: oklch(0.81 0.08 188); @@ -853,14 +854,14 @@ html.accent-aqua.dark { html.accent-acid-green { --tint-h: 112; - --primary: oklch(0.7 0.2 112); + --accent-primary: oklch(0.7 0.2 112); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.7 0.2 112); --sidebar-primary: oklch(0.7 0.2 112); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-acid-green.dark { - --primary: oklch(0.82 0.17 112); + --accent-primary: oklch(0.82 0.17 112); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.82 0.17 112); --sidebar-primary: oklch(0.82 0.17 112); @@ -869,14 +870,14 @@ html.accent-acid-green.dark { html.accent-pistachio { --tint-h: 112; - --primary: oklch(0.8 0.11 112); + --accent-primary: oklch(0.8 0.11 112); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.8 0.11 112); --sidebar-primary: oklch(0.8 0.11 112); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-pistachio.dark { - --primary: oklch(0.88 0.09 112); + --accent-primary: oklch(0.88 0.09 112); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.88 0.09 112); --sidebar-primary: oklch(0.88 0.09 112); @@ -885,14 +886,14 @@ html.accent-pistachio.dark { html.accent-electric-blue { --tint-h: 230; - --primary: oklch(0.54 0.24 230); + --accent-primary: oklch(0.54 0.24 230); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.54 0.24 230); --sidebar-primary: oklch(0.54 0.24 230); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-electric-blue.dark { - --primary: oklch(0.73 0.19 230); + --accent-primary: oklch(0.73 0.19 230); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.73 0.19 230); --sidebar-primary: oklch(0.73 0.19 230); @@ -901,14 +902,14 @@ html.accent-electric-blue.dark { html.accent-baby-blue { --tint-h: 230; - --primary: oklch(0.68 0.12 230); + --accent-primary: oklch(0.68 0.12 230); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.12 230); --sidebar-primary: oklch(0.68 0.12 230); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-baby-blue.dark { - --primary: oklch(0.79 0.1 230); + --accent-primary: oklch(0.79 0.1 230); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.79 0.1 230); --sidebar-primary: oklch(0.79 0.1 230); @@ -917,14 +918,14 @@ html.accent-baby-blue.dark { html.accent-ultramarine { --tint-h: 247; - --primary: oklch(0.5 0.28 247); + --accent-primary: oklch(0.5 0.28 247); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.5 0.28 247); --sidebar-primary: oklch(0.5 0.28 247); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-ultramarine.dark { - --primary: oklch(0.7 0.22 247); + --accent-primary: oklch(0.7 0.22 247); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.7 0.22 247); --sidebar-primary: oklch(0.7 0.22 247); @@ -933,14 +934,14 @@ html.accent-ultramarine.dark { html.accent-bluebell { --tint-h: 270; - --primary: oklch(0.68 0.125 270); + --accent-primary: oklch(0.68 0.125 270); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.125 270); --sidebar-primary: oklch(0.68 0.125 270); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-bluebell.dark { - --primary: oklch(0.78 0.12 270); + --accent-primary: oklch(0.78 0.12 270); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.78 0.12 270); --sidebar-primary: oklch(0.78 0.12 270); @@ -949,14 +950,14 @@ html.accent-bluebell.dark { html.accent-purple { --tint-h: 284; - --primary: oklch(0.51 0.25 284); + --accent-primary: oklch(0.51 0.25 284); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.51 0.25 284); --sidebar-primary: oklch(0.51 0.25 284); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-purple.dark { - --primary: oklch(0.72 0.21 284); + --accent-primary: oklch(0.72 0.21 284); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.72 0.21 284); --sidebar-primary: oklch(0.72 0.21 284); @@ -965,14 +966,14 @@ html.accent-purple.dark { html.accent-thistle { --tint-h: 284; - --primary: oklch(0.68 0.125 284); + --accent-primary: oklch(0.68 0.125 284); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.125 284); --sidebar-primary: oklch(0.68 0.125 284); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-thistle.dark { - --primary: oklch(0.78 0.12 284); + --accent-primary: oklch(0.78 0.12 284); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.78 0.12 284); --sidebar-primary: oklch(0.78 0.12 284); @@ -981,14 +982,14 @@ html.accent-thistle.dark { html.accent-amethyst { --tint-h: 302; - --primary: oklch(0.54 0.24 302); + --accent-primary: oklch(0.54 0.24 302); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.54 0.24 302); --sidebar-primary: oklch(0.54 0.24 302); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-amethyst.dark { - --primary: oklch(0.73 0.2 302); + --accent-primary: oklch(0.73 0.2 302); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.73 0.2 302); --sidebar-primary: oklch(0.73 0.2 302); @@ -997,14 +998,14 @@ html.accent-amethyst.dark { html.accent-mauve { --tint-h: 302; - --primary: oklch(0.68 0.12 302); + --accent-primary: oklch(0.68 0.12 302); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.12 302); --sidebar-primary: oklch(0.68 0.12 302); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-mauve.dark { - --primary: oklch(0.79 0.11 302); + --accent-primary: oklch(0.79 0.11 302); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.79 0.11 302); --sidebar-primary: oklch(0.79 0.11 302); @@ -1013,14 +1014,14 @@ html.accent-mauve.dark { html.accent-raspberry { --tint-h: 344; - --primary: oklch(0.56 0.23 344); + --accent-primary: oklch(0.56 0.23 344); --primary-foreground: oklch(0.985 0 0); --ring: oklch(0.56 0.23 344); --sidebar-primary: oklch(0.56 0.23 344); --sidebar-primary-foreground: oklch(0.985 0 0); } html.accent-raspberry.dark { - --primary: oklch(0.74 0.19 344); + --accent-primary: oklch(0.74 0.19 344); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.74 0.19 344); --sidebar-primary: oklch(0.74 0.19 344); @@ -1029,14 +1030,14 @@ html.accent-raspberry.dark { html.accent-rose-quartz { --tint-h: 344; - --primary: oklch(0.68 0.115 344); + --accent-primary: oklch(0.68 0.115 344); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.68 0.115 344); --sidebar-primary: oklch(0.68 0.115 344); --sidebar-primary-foreground: oklch(0.145 0 0); } html.accent-rose-quartz.dark { - --primary: oklch(0.8 0.1 344); + --accent-primary: oklch(0.8 0.1 344); --primary-foreground: oklch(0.145 0 0); --ring: oklch(0.8 0.1 344); --sidebar-primary: oklch(0.8 0.1 344); diff --git a/client/src/assets/theme/bridge.css b/client/src/assets/theme/bridge.css index daf165b8c..02e0b6af7 100644 --- a/client/src/assets/theme/bridge.css +++ b/client/src/assets/theme/bridge.css @@ -2,6 +2,7 @@ Maps CSS variables → Tailwind utility classes. ────────────────────────────────────────────────────────────── */ @theme inline { + --radius-xs: calc(var(--radius) - 6px); --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); @@ -9,9 +10,9 @@ --radius-2xl: calc(var(--radius) + 8px); --radius-3xl: calc(var(--radius) + 12px); - --font-sans: 'Inter Variable', ui-sans-serif, system-ui, -apple-system, sans-serif; - --font-serif: 'Fraunces Variable', ui-serif, Georgia, serif; - --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace; + --font-sans: var(--app-font-sans); + --font-serif: var(--app-font-serif); + --font-mono: var(--app-font-mono); --color-background: var(--background); --color-foreground: var(--foreground); diff --git a/client/src/assets/theme/styles/nostalgia.css b/client/src/assets/theme/styles/nostalgia.css new file mode 100644 index 000000000..79abbc92b --- /dev/null +++ b/client/src/assets/theme/styles/nostalgia.css @@ -0,0 +1,119 @@ +/* ── Nostalgia style ───────────────────────────────────────── + Neutral grounds from the surface palette, system type, a flat + shell and a tall accent glow over a faint grid of squares. + Only reassigns tokens, so components never ask which style is + active. Accent, radius and background stay the user's: the + accent is only re-shaded (from --accent-primary), never replaced. + + Same specificity as the accent classes and imported after them, + so where both set a token (--sidebar) the style wins. +────────────────────────────────────────────────────────────── */ +html[data-style='nostalgia'] { + --app-font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; + --app-font-serif: var(--app-font-sans); + + --background: var(--surface-ground); + --foreground: oklch(0.2 calc(var(--surface-c) * 0.6) var(--surface-h)); + --card: var(--surface-card); + --card-foreground: var(--foreground); + --popover: var(--card); + --popover-foreground: var(--foreground); + --secondary: oklch(calc(0.94 + var(--surface-l) * 0.4) calc(var(--surface-c) * 0.6) var(--surface-h)); + --secondary-foreground: var(--foreground); + --muted: oklch(calc(0.94 + var(--surface-l) * 0.4) calc(var(--surface-c) * 0.6) var(--surface-h)); + --muted-foreground: oklch(0.5 calc(var(--surface-c) * 0.6) var(--surface-h)); + --accent: oklch(calc(0.94 + var(--surface-l) * 0.4) calc(var(--surface-c) * 0.6) var(--surface-h)); + --accent-foreground: var(--foreground); + --border: var(--surface-edge); + --input: oklch(calc(0.85 + var(--surface-l) * 0.4) calc(var(--surface-c) * 1.2) var(--surface-h)); + + --surface-1: var(--card); + --surface-2: oklch(calc(0.965 + var(--surface-l) * 0.4) calc(var(--surface-c) * 0.6) var(--surface-h)); + --surface-3: var(--muted); + --surface-4: oklch(calc(0.915 + var(--surface-l) * 0.4) calc(var(--surface-c) * 0.6) var(--surface-h)); + --volume-unread: oklch(calc(0.86 + var(--surface-l) * 0.4) calc(var(--surface-c) * 0.8) var(--surface-h)); + --dot-color: oklch(calc(0.83 + var(--surface-l) * 0.4) calc(var(--surface-c) * 0.8) var(--surface-h)); + --scrollbar-thumb: oklch(0.8 calc(var(--surface-c) * 0.8) var(--surface-h)); + --scrollbar-thumb-hover: oklch(0.7 calc(var(--surface-c) * 0.8) var(--surface-h)); + + --sidebar: var(--card); + --sidebar-foreground: var(--foreground); + --sidebar-accent: var(--muted); + --sidebar-accent-foreground: var(--foreground); + --sidebar-border: var(--border); + /* Book counts wear the accent hue, held dark enough to clear AA on the sidebar card. */ + --sidebar-count-foreground: oklch(from var(--primary) min(l, 0.5) c h); + --sidebar-heading-foreground: var(--foreground); + --sidebar-heading-size: 12px; + --sidebar-heading-weight: 700; + --sidebar-heading-tracking: 0.06em; + --sidebar-count-bg: transparent; + --sidebar-count-size: 14px; + --sidebar-count-weight: 400; + /* The classic active row is a faint wash, so the accent text and count on it keep their full contrast. */ + --sidebar-active-bg: color-mix(in oklch, var(--primary) 7%, transparent); + --sidebar-active-weight: 700; + + --shell-border: var(--border); + --shell-backdrop: none; + --shell-shadow: 0 3px 5px oklch(0 0 0 / 0.02), 0 0 2px oklch(0 0 0 / 0.05), 0 1px 4px oklch(0 0 0 / 0.08); + --shell-accent-wash: color-mix(in oklch, var(--primary) 8%, transparent); + --shell-accent-tint: color-mix(in oklch, var(--primary) 16%, transparent); + + --glow-image: radial-gradient(50% 50% at center -25px, color-mix(in oklch, var(--primary) 38%, transparent) 0%, transparent 100%); + --glow-band: 20rem; + --glow-texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 84 84' fill='%23000'%3E%3Crect x='1' y='1' width='19' height='19' fill-opacity='0.044'/%3E%3Crect x='22' y='1' width='19' height='19' fill-opacity='0.058'/%3E%3Crect x='43' y='1' width='19' height='19' fill-opacity='0.042'/%3E%3Crect x='64' y='1' width='19' height='19' fill-opacity='0.035'/%3E%3Crect x='1' y='22' width='19' height='19' fill-opacity='0.059'/%3E%3Crect x='22' y='22' width='19' height='19' fill-opacity='0.02'/%3E%3Crect x='43' y='22' width='19' height='19' fill-opacity='0.054'/%3E%3Crect x='64' y='22' width='19' height='19' fill-opacity='0.03'/%3E%3Crect x='1' y='43' width='19' height='19' fill-opacity='0.024'/%3E%3Crect x='22' y='43' width='19' height='19' fill-opacity='0.023'/%3E%3Crect x='43' y='43' width='19' height='19' fill-opacity='0.031'/%3E%3Crect x='64' y='43' width='19' height='19' fill-opacity='0.052'/%3E%3Crect x='1' y='64' width='19' height='19' fill-opacity='0.026'/%3E%3Crect x='22' y='64' width='19' height='19' fill-opacity='0.042'/%3E%3Crect x='43' y='64' width='19' height='19' fill-opacity='0.045'/%3E%3Crect x='64' y='64' width='19' height='19' fill-opacity='0.034'/%3E%3C/svg%3E"); + --glow-texture-size: 107px 107px; + + --cover-hover-transform: translateY(-3px); + + --format-chip-fill: 18%; + --format-chip-border: 55%; + + --chip-genre-bg: oklch(0.6 0.2 25 / 0.12); + --chip-genre-fg: oklch(0.5 0.17 25); + --chip-genre-border: oklch(0.6 0.2 25 / 0.35); + --chip-tag-bg: oklch(0.65 0.17 150 / 0.12); + --chip-tag-fg: oklch(0.47 0.13 150); + --chip-tag-border: oklch(0.65 0.17 150 / 0.35); +} + +/* The classic ash ladder, shifted by the palette's --surface-l. Ground, card and edge come from surfaces.css. The style pins surface brightness to 0, so + --bg-lift adds nothing here. Light mode takes 40% of the shift: enough to tell greys apart, not to dim a page. */ +html[data-style='nostalgia'].dark { + /* Accents at their classic 400-shade brightness: the darker ones (greens, lime) lift, the rest already sit there. */ + --primary: oklch(from var(--accent-primary) max(l, 0.78) c h); + + --foreground: oklch(1 0 0); + --secondary: oklch(calc(0.307 + var(--bg-lift) + var(--surface-l)) var(--surface-c) var(--surface-h)); + --muted: oklch(calc(0.307 + var(--bg-lift) + var(--surface-l)) var(--surface-c) var(--surface-h)); + --muted-foreground: oklch(0.76 calc(var(--surface-c) * 0.6) var(--surface-h)); + --accent: oklch(calc(0.307 + var(--bg-lift) + var(--surface-l)) var(--surface-c) var(--surface-h)); + --input: oklch(calc(0.432 + var(--bg-lift) + var(--surface-l)) calc(var(--surface-c) * 1.4) var(--surface-h)); + + --surface-2: oklch(calc(0.262 + var(--bg-lift) + var(--surface-l)) var(--surface-c) var(--surface-h)); + --surface-4: oklch(calc(0.362 + var(--bg-lift) + var(--surface-l)) var(--surface-c) var(--surface-h)); + --volume-unread: oklch(calc(0.362 + var(--bg-lift) + var(--surface-l)) var(--surface-c) var(--surface-h)); + --dot-color: oklch(calc(0.302 + var(--bg-lift) + var(--surface-l)) var(--surface-c) var(--surface-h)); + --scrollbar-thumb: oklch(0.38 var(--surface-c) var(--surface-h)); + --scrollbar-thumb-hover: oklch(0.48 var(--surface-c) var(--surface-h)); + + --sidebar-count-foreground: oklch(from var(--primary) max(l, 0.72) c h); + + --glow-image: radial-gradient(50% 50% at center -25px, color-mix(in oklch, var(--primary) 60%, transparent) 0%, transparent 100%); + --glow-texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 84 84' fill='%23fff'%3E%3Crect x='1' y='1' width='19' height='19' fill-opacity='0.056'/%3E%3Crect x='22' y='1' width='19' height='19' fill-opacity='0.042'/%3E%3Crect x='43' y='1' width='19' height='19' fill-opacity='0.082'/%3E%3Crect x='64' y='1' width='19' height='19' fill-opacity='0.036'/%3E%3Crect x='1' y='22' width='19' height='19' fill-opacity='0.073'/%3E%3Crect x='22' y='22' width='19' height='19' fill-opacity='0.059'/%3E%3Crect x='43' y='22' width='19' height='19' fill-opacity='0.035'/%3E%3Crect x='64' y='22' width='19' height='19' fill-opacity='0.071'/%3E%3Crect x='1' y='43' width='19' height='19' fill-opacity='0.033'/%3E%3Crect x='22' y='43' width='19' height='19' fill-opacity='0.065'/%3E%3Crect x='43' y='43' width='19' height='19' fill-opacity='0.036'/%3E%3Crect x='64' y='43' width='19' height='19' fill-opacity='0.037'/%3E%3Crect x='1' y='64' width='19' height='19' fill-opacity='0.064'/%3E%3Crect x='22' y='64' width='19' height='19' fill-opacity='0.096'/%3E%3Crect x='43' y='64' width='19' height='19' fill-opacity='0.04'/%3E%3Crect x='64' y='64' width='19' height='19' fill-opacity='0.048'/%3E%3C/svg%3E"); + + /* Solid chips in a deep shade of each format's hue with white ink, as the classic look wore them; at this + lightness every format clears 5.4:1. */ + --format-chip-fill: 100%; + --format-chip-border: 100%; + --format-chip-fill-l: 0.5; + --format-chip-ink: oklch(1 0 0); + + --chip-genre-bg: oklch(0.64 0.2 25 / 0.18); + --chip-genre-fg: oklch(0.82 0.1 25); + --chip-genre-border: oklch(0.64 0.2 25 / 0.35); + --chip-tag-bg: oklch(0.72 0.17 150 / 0.18); + --chip-tag-fg: oklch(0.84 0.12 150); + --chip-tag-border: oklch(0.72 0.17 150 / 0.35); +} diff --git a/client/src/assets/theme/surfaces.css b/client/src/assets/theme/surfaces.css new file mode 100644 index 000000000..b19143d8f --- /dev/null +++ b/client/src/assets/theme/surfaces.css @@ -0,0 +1,128 @@ +/* ── Surface palettes ──────────────────────────────────────── + Neutral grounds for styles that declare a surface palette + control. A palette is a hue, a chroma and a small lightness + offset on the style's ladder (darker for onyx, lighter for + charcoal), bounded so every palette keeps the ladder's AA + contrast. Applied as data-surface on , or on a swatch + to preview a palette in place. +────────────────────────────────────────────────────────────── */ +[data-surface='onyx'] { + --surface-h: 0; + --surface-c: 0; + --surface-l: -0.06; +} +[data-surface='carbon'] { + --surface-h: 248; + --surface-c: 0.005; + --surface-l: -0.035; +} +[data-surface='neutral'] { + --surface-h: 0; + --surface-c: 0; + --surface-l: -0.015; +} +[data-surface='zinc'] { + --surface-h: 286; + --surface-c: 0.006; + --surface-l: -0.025; +} +[data-surface='iron'] { + --surface-h: 248; + --surface-c: 0.007; + --surface-l: 0; +} +[data-surface='steel'] { + --surface-h: 258; + --surface-c: 0.01; + --surface-l: -0.005; +} +[data-surface='ash'] { + --surface-h: 245; + --surface-c: 0.012; + --surface-l: 0; +} +[data-surface='smoke'] { + --surface-h: 270; + --surface-c: 0.006; + --surface-l: 0.005; +} +[data-surface='charcoal'] { + --surface-h: 0; + --surface-c: 0; + --surface-l: 0.025; +} +[data-surface='slate'] { + --surface-h: 262; + --surface-c: 0.03; + --surface-l: -0.038; +} +[data-surface='midnight-blue'] { + --surface-h: 252; + --surface-c: 0.022; + --surface-l: 0.027; +} +[data-surface='ocean'] { + --surface-h: 228; + --surface-c: 0.034; + --surface-l: 0.038; +} +[data-surface='pine'] { + --surface-h: 165; + --surface-c: 0.022; + --surface-l: 0; +} +[data-surface='olive'] { + --surface-h: 135; + --surface-c: 0.018; + --surface-l: 0.03; +} +[data-surface='stone'] { + --surface-h: 58; + --surface-c: 0.009; + --surface-l: -0.02; +} +[data-surface='sepia'] { + --surface-h: 70; + --surface-c: 0.024; + --surface-l: 0; +} +[data-surface='crimson'] { + --surface-h: 18; + --surface-c: 0.016; + --surface-l: 0.018; +} +[data-surface='plum'] { + --surface-h: 330; + --surface-c: 0.02; + --surface-l: 0; +} + +/* The ground, card and edge of the ladder, in the active mode, for whichever palette the element carries. The + Nostalgia style paints its surfaces from these, and a picker tile previews a palette with the very same values. */ +[data-surface] { + --surface-ground: oklch(calc(0.955 + var(--surface-l) * 0.4) calc(var(--surface-c) * 0.6) var(--surface-h)); + --surface-card: oklch(calc(0.99 + var(--surface-l) * 0.4) calc(var(--surface-c) * 0.3) var(--surface-h)); + --surface-edge: oklch(calc(0.87 + var(--surface-l) * 0.4) calc(var(--surface-c) * 1.2) var(--surface-h)); +} +.dark[data-surface], +.dark [data-surface] { + --surface-ground: oklch(calc(0.167 + var(--bg-lift) + var(--surface-l)) var(--surface-c) var(--surface-h)); + --surface-card: oklch(calc(0.232 + var(--bg-lift) + var(--surface-l)) var(--surface-c) var(--surface-h)); + --surface-edge: oklch(calc(0.402 + var(--bg-lift) + var(--surface-l)) calc(var(--surface-c) * 1.4) var(--surface-h)); +} + +/* Picker tile: a small window, ground behind a card panel. */ +.surface-tile { + position: relative; + overflow: hidden; + background-color: var(--surface-ground); + border: 1px solid var(--surface-edge); +} +.surface-tile::before { + content: ''; + position: absolute; + inset: 34% -1px -1px 26%; + border: 1px solid var(--surface-edge); + border-top-left-radius: 4px; + background-color: var(--surface-card); +} diff --git a/client/src/assets/theme/tokens.css b/client/src/assets/theme/tokens.css index 09674cd08..bed8aa13f 100644 --- a/client/src/assets/theme/tokens.css +++ b/client/src/assets/theme/tokens.css @@ -25,7 +25,9 @@ --popover: oklch(0.975 var(--tint-c-surface) var(--tint-h)); --popover-foreground: oklch(0.145 var(--tint-c-surface) var(--tint-h)); - --primary: oklch(0.21 var(--tint-c-surface) var(--tint-h)); + /* The accent class sets --accent-primary; a style may derive --primary from it instead. */ + --accent-primary: oklch(0.21 var(--tint-c-surface) var(--tint-h)); + --primary: var(--accent-primary); --primary-foreground: oklch(0.985 0.004 var(--tint-h)); --secondary: oklch(0.955 var(--tint-c-surface) var(--tint-h)); @@ -39,12 +41,6 @@ --destructive: oklch(0.577 0.245 27.325); --destructive-foreground: oklch(0.985 0 0); - --success: oklch(0.52 0.16 150); - --success-foreground: oklch(0.985 0 0); - --warning: oklch(0.57 0.15 75); - --warning-foreground: oklch(0.145 0 0); - --info: oklch(0.52 0.17 245); - --info-foreground: oklch(0.985 0 0); --success: oklch(0.52 0.14 148); --success-foreground: oklch(0.985 0 0); @@ -56,6 +52,7 @@ /* In flight: neither finished nor broken. Tuned per theme for the same reason. */ --info: oklch(0.55 0.12 255); + --info-foreground: oklch(0.985 0 0); --star-highlight: oklch(0.76 0.18 90); @@ -129,6 +126,16 @@ /* Shape */ --radius: 0.625rem; + /* The default surface palette (steel, as in surfaces.css), so a ladder that reads these is valid before data-surface lands. */ + --surface-h: 258; + --surface-c: 0.01; + --surface-l: -0.005; + + /* Type. The bridge maps the Tailwind font utilities onto these, so a style can swap them at runtime. */ + --app-font-sans: 'Inter Variable', ui-sans-serif, system-ui, -apple-system, sans-serif; + --app-font-serif: 'Fraunces Variable', ui-serif, Georgia, serif; + --app-font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace; + /* App shell (sidebar + header): one card gap, one material. --shell-surface-opacity is user-controlled and overwritten on . */ --shell-gap: 0.75rem; @@ -140,6 +147,43 @@ --shell-accent-tint: color-mix(in oklch, var(--primary) 12%, transparent); --shell-accent-line: color-mix(in oklch, var(--primary) 30%, transparent); --shell-border: var(--shell-accent-line); + --shell-backdrop: blur(24px) saturate(150%); + --shell-shadow: var(--elevation-lg); + + /* Accent glow behind the top of the shell (.glow-wrapper). --glow-band is the style's own reach and + --glow-reach the user's multiplier on it, written on . A texture keeps its tile size at any reach; + only the fade that reveals it follows the band. */ + --glow-reach: 0.8; + --glow-band: 12rem; + --glow-image: radial-gradient(50% 50% at center -25px, color-mix(in oklch, var(--primary) 35%, transparent) 0%, transparent 100%); + --glow-texture: none; + --glow-texture-size: auto; + + /* How a grid cover answers the pointer. */ + --cover-hover-transform: scale(1.02); + + /* Sidebar section labels, counts and the active navigation row. */ + --sidebar-heading-foreground: var(--muted-foreground); + --sidebar-heading-size: 11px; + --sidebar-heading-weight: 500; + --sidebar-heading-tracking: 0.14em; + --sidebar-count-bg: var(--shell-accent-tint); + --sidebar-count-size: 11px; + --sidebar-count-weight: 600; + --sidebar-active-bg: var(--shell-accent-tint); + --sidebar-active-weight: 500; + + /* How strongly a format chip wears its format colour (see formatChipStyle). */ + --format-chip-fill: 10%; + --format-chip-border: 40%; + + /* Book detail metadata chips. Tag ink is tuned like --warning so it clears AA on a light card. */ + --chip-genre-bg: var(--muted); + --chip-genre-fg: var(--foreground); + --chip-genre-border: transparent; + --chip-tag-bg: oklch(0.769 0.188 70.08 / 0.1); + --chip-tag-fg: oklch(0.52 0.13 68); + --chip-tag-border: oklch(0.769 0.188 70.08 / 0.3); --dot-color: oklch(0.82 var(--tint-c-surface) var(--tint-h)); @@ -250,31 +294,6 @@ --audit-collections: oklch(0.55 0.09 255); --audit-integrations: oklch(0.58 0.15 150); --audit-settings: oklch(0.55 0.15 25); - - /* File format, worn as a chip whose own text carries the colour. Tuned per theme for the same - reason every other text colour is: one set of hex values for both themes left the brightest - (yellow on white, around 1.9:1) unreadable in light mode and the darkest invisible in dark. */ - --pill-format-default: oklch(0.55 0.02 260); - --pill-format-epub: oklch(0.55 0.14 150); - --pill-format-kepub: oklch(0.55 0.12 178); - --pill-format-mobi: oklch(0.55 0.18 275); - --pill-format-azw3: oklch(0.53 0.11 185); - --pill-format-azw: oklch(0.55 0.14 235); - --pill-format-fb2: oklch(0.55 0.17 355); - --pill-format-djvu: oklch(0.55 0.04 255); - --pill-format-txt: oklch(0.55 0.03 60); - --pill-format-pdf: oklch(0.55 0.17 25); - --pill-format-cbz: oklch(0.55 0.16 260); - --pill-format-cbr: oklch(0.58 0.15 55); - --pill-format-cb7: oklch(0.55 0.19 300); - --pill-format-cbx: oklch(0.55 0.17 325); - --pill-format-m4b: oklch(0.58 0.13 75); - --pill-format-m4a: oklch(0.58 0.13 95); - --pill-format-mp3: oklch(0.56 0.15 145); - --pill-format-opus: oklch(0.55 0.11 205); - --pill-format-ogg: oklch(0.56 0.15 130); - --pill-format-flac: oklch(0.55 0.13 165); - --pill-format-readalong: oklch(0.52 0.1 186); } @media (min-width: 40rem) { @@ -304,7 +323,7 @@ --popover: oklch(calc(0.18 + var(--bg-lift)) var(--tint-c-surface) var(--tint-h)); --popover-foreground: oklch(0.985 0.001 var(--tint-h)); - --primary: oklch(0.91 var(--tint-c-surface) var(--tint-h)); + --accent-primary: oklch(0.91 var(--tint-c-surface) var(--tint-h)); --primary-foreground: oklch(0.18 var(--tint-c-surface) var(--tint-h)); --secondary: oklch(calc(0.245 + var(--bg-lift)) var(--tint-c-surface) var(--tint-h)); @@ -318,12 +337,6 @@ --destructive: oklch(0.704 0.191 22.216); --destructive-foreground: oklch(0.985 0 0); - --success: oklch(0.74 0.15 150); - --success-foreground: oklch(0.145 0 0); - --warning: oklch(0.78 0.14 75); - --warning-foreground: oklch(0.145 0 0); - --info: oklch(0.75 0.14 245); - --info-foreground: oklch(0.145 0 0); --success: oklch(0.72 0.15 148); --success-foreground: oklch(0.145 0 0); @@ -332,6 +345,7 @@ --warning-foreground: oklch(0.145 0 0); --info: oklch(0.72 0.12 255); + --info-foreground: oklch(0.145 0 0); --star-highlight: oklch(0.84 0.17 95); @@ -390,6 +404,8 @@ --scrollbar-thumb: oklch(0.35 var(--tint-c) var(--tint-h)); --scrollbar-thumb-hover: oklch(0.45 var(--tint-c) var(--tint-h)); + --chip-tag-fg: oklch(0.828 0.189 84.429); + /* Lifted lightness so pills read on dark surfaces */ --pill-web: oklch(0.72 0.14 245); --pill-ios: oklch(0.75 0.14 150); @@ -474,30 +490,4 @@ --audit-collections: oklch(0.72 0.09 255); --audit-integrations: oklch(0.75 0.13 150); --audit-settings: oklch(0.72 0.15 25); - - /* File format, worn as a chip whose own text carries the colour. Tuned per theme for the same - reason every other text colour is: one set of hex values for both themes left the brightest - (yellow on white, around 1.9:1) unreadable in light mode and the darkest invisible in dark. */ - - --pill-format-default: oklch(0.75 0.02 260); - --pill-format-epub: oklch(0.75 0.13 150); - --pill-format-kepub: oklch(0.75 0.11 178); - --pill-format-mobi: oklch(0.72 0.16 275); - --pill-format-azw3: oklch(0.76 0.11 185); - --pill-format-azw: oklch(0.72 0.13 235); - --pill-format-fb2: oklch(0.73 0.15 355); - --pill-format-djvu: oklch(0.75 0.04 255); - --pill-format-txt: oklch(0.76 0.03 60); - --pill-format-pdf: oklch(0.72 0.15 25); - --pill-format-cbz: oklch(0.72 0.14 260); - --pill-format-cbr: oklch(0.76 0.13 55); - --pill-format-cb7: oklch(0.72 0.17 300); - --pill-format-cbx: oklch(0.73 0.15 325); - --pill-format-m4b: oklch(0.79 0.13 75); - --pill-format-m4a: oklch(0.8 0.13 95); - --pill-format-mp3: oklch(0.78 0.15 145); - --pill-format-opus: oklch(0.76 0.11 205); - --pill-format-ogg: oklch(0.78 0.15 130); - --pill-format-flac: oklch(0.75 0.13 165); - --pill-format-readalong: oklch(0.78 0.11 186); } diff --git a/client/src/components/AppHeader.vue b/client/src/components/AppHeader.vue index ad913d0cf..979c45859 100644 --- a/client/src/components/AppHeader.vue +++ b/client/src/components/AppHeader.vue @@ -42,7 +42,10 @@ import RadiusPicker from '@/components/RadiusPicker.vue' import BackgroundPicker from '@/components/BackgroundPicker.vue' import ThemePicker from '@/components/ThemePicker.vue' import SurfaceBrightnessPicker from '@/components/SurfaceBrightnessPicker.vue' -import SurfacePicker from '@/components/SurfacePicker.vue' +import SurfaceOpacityPicker from '@/components/SurfaceOpacityPicker.vue' +import StylePicker from '@/components/StylePicker.vue' +import SurfacePalettePicker from '@/components/SurfacePalettePicker.vue' +import GlowReachPicker from '@/components/GlowReachPicker.vue' import { useGlobalSearch, type GlobalSearchResult } from '@/features/book/composables/useGlobalSearch' import BookCoverImage from '@/features/book/components/BookCoverImage.vue' import { useAuth } from '@/features/auth/composables/useAuth' @@ -71,6 +74,8 @@ const { onLibraryUploadCompleted } = useLibraryUploadEvents() const { subscribe: subscribeNotifications } = useNotifications() const { hasUnseen: hasUnseenWhatsNew } = useWhatsNew() const themeStore = useThemeStore() +const showSurfaceOpacity = computed(() => themeStore.appearanceControls.surfaceOpacity) +const showSurfaceBrightness = computed(() => themeStore.resolvedTheme === 'dark' && themeStore.appearanceControls.brightness) const localeStore = useLocaleStore() const { openLegalNotices } = useLegalNotices() const currentLanguageLabel = computed(() => LOCALE_LABELS[localeStore.locale]) @@ -343,7 +348,7 @@ function resultFormatEntries(result: GlobalSearchResult) {