feat: four OKLCH palette options + dev-only switcher
Extracts each palette into its own module under src/themes/, scoped to :root[data-palette='<slug>'] so multiple can coexist and a JS attribute swap is enough to flip the whole site: - stone-warm — bone + matte-black, gallery-quiet (current default) - desert-clay — warm cream with terracotta undertone, evening light - forest-ash — sage-tinted neutral with mossy accent, nature-leaning - charcoal-cream — high-contrast monochrome, Asheville moody by default usePalette() reads ?palette=<slug>, falls back to localStorage, then to stone-warm. Active palette is written to <html data-palette>. PaletteSwitcher (the round Palette icon at bottom-right) only renders when import.meta.env.DEV is true — Nicholette can use it to compare the four side-by-side, but it ships out of the production bundle. To make a different palette the production default, edit the bare :root + .dark blocks at the bottom of themes/index.css. That keeps the runtime swap working as a preview channel and lets us ship a single hard-coded chrome once she chooses. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d9f52c6e7b
commit
f0980d7fb5
9 changed files with 356 additions and 45 deletions
|
|
@ -3,6 +3,9 @@ import { RouterView } from 'vue-router'
|
||||||
import { Toaster } from '@/components/ui/sonner'
|
import { Toaster } from '@/components/ui/sonner'
|
||||||
import SiteHeader from './SiteHeader.vue'
|
import SiteHeader from './SiteHeader.vue'
|
||||||
import SiteFooter from './SiteFooter.vue'
|
import SiteFooter from './SiteFooter.vue'
|
||||||
|
import PaletteSwitcher from './PaletteSwitcher.vue'
|
||||||
|
|
||||||
|
const isDev = import.meta.env.DEV
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -13,5 +16,6 @@ import SiteFooter from './SiteFooter.vue'
|
||||||
</main>
|
</main>
|
||||||
<SiteFooter />
|
<SiteFooter />
|
||||||
<Toaster position="bottom-right" />
|
<Toaster position="bottom-right" />
|
||||||
|
<PaletteSwitcher v-if="isDev" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
41
src/components/layout/PaletteSwitcher.vue
Normal file
41
src/components/layout/PaletteSwitcher.vue
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Palette } from '@lucide/vue'
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuLabel,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/components/ui/dropdown-menu'
|
||||||
|
import { PALETTES, usePalette, type PaletteSlug } from '@/composables/usePalette'
|
||||||
|
|
||||||
|
const { palette, set } = usePalette()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger
|
||||||
|
class="border-border bg-background/85 hover:bg-background fixed right-4 bottom-4 z-50 inline-flex h-10 w-10 items-center justify-center rounded-full border shadow-lg backdrop-blur transition-colors"
|
||||||
|
aria-label="Switch color palette"
|
||||||
|
>
|
||||||
|
<Palette class="h-4 w-4" />
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end" side="top" class="w-72">
|
||||||
|
<DropdownMenuLabel class="text-xs uppercase tracking-[0.18em]">
|
||||||
|
Palette (dev only)
|
||||||
|
</DropdownMenuLabel>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuItem
|
||||||
|
v-for="p in PALETTES"
|
||||||
|
:key="p.slug"
|
||||||
|
class="flex flex-col items-start gap-0.5 py-2.5"
|
||||||
|
:class="palette === p.slug ? 'bg-accent' : ''"
|
||||||
|
@select="set(p.slug as PaletteSlug)"
|
||||||
|
>
|
||||||
|
<span class="font-serif text-sm">{{ p.label }}</span>
|
||||||
|
<span class="text-muted-foreground text-xs">{{ p.description }}</span>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</template>
|
||||||
54
src/composables/usePalette.ts
Normal file
54
src/composables/usePalette.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { ref, watchEffect } from 'vue'
|
||||||
|
|
||||||
|
export const PALETTES = [
|
||||||
|
{
|
||||||
|
slug: 'stone-warm',
|
||||||
|
label: 'Stone Warm',
|
||||||
|
description: 'Bone background, matte-black ink. Gallery-quiet.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'desert-clay',
|
||||||
|
label: 'Desert Clay',
|
||||||
|
description: 'Warm cream with terracotta undertone. Evening light.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'forest-ash',
|
||||||
|
label: 'Forest & Ash',
|
||||||
|
description: 'Sage-tinted neutral, mossy accent. Nature integrated.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'charcoal-cream',
|
||||||
|
label: 'Charcoal & Cream',
|
||||||
|
description: 'High-contrast monochrome. Moody architectural.',
|
||||||
|
},
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export type PaletteSlug = (typeof PALETTES)[number]['slug']
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'ewd:palette'
|
||||||
|
const DEFAULT: PaletteSlug = 'stone-warm'
|
||||||
|
|
||||||
|
function initial(): PaletteSlug {
|
||||||
|
if (typeof window === 'undefined') return DEFAULT
|
||||||
|
const url = new URL(window.location.href)
|
||||||
|
const fromQuery = url.searchParams.get('palette') as PaletteSlug | null
|
||||||
|
if (fromQuery && PALETTES.some((p) => p.slug === fromQuery)) return fromQuery
|
||||||
|
const stored = window.localStorage.getItem(STORAGE_KEY) as PaletteSlug | null
|
||||||
|
if (stored && PALETTES.some((p) => p.slug === stored)) return stored
|
||||||
|
return DEFAULT
|
||||||
|
}
|
||||||
|
|
||||||
|
const palette = ref<PaletteSlug>(initial())
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
if (typeof document === 'undefined') return
|
||||||
|
document.documentElement.setAttribute('data-palette', palette.value)
|
||||||
|
window.localStorage.setItem(STORAGE_KEY, palette.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
export function usePalette() {
|
||||||
|
function set(slug: PaletteSlug) {
|
||||||
|
palette.value = slug
|
||||||
|
}
|
||||||
|
return { palette, set }
|
||||||
|
}
|
||||||
|
|
@ -1,53 +1,9 @@
|
||||||
@import 'tailwindcss';
|
@import 'tailwindcss';
|
||||||
@import 'tw-animate-css';
|
@import 'tw-animate-css';
|
||||||
|
@import './themes/index.css';
|
||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
:root {
|
|
||||||
--background: oklch(0.985 0.005 80);
|
|
||||||
--foreground: oklch(0.2 0.012 60);
|
|
||||||
--card: oklch(0.985 0.005 80);
|
|
||||||
--card-foreground: oklch(0.2 0.012 60);
|
|
||||||
--popover: oklch(0.985 0.005 80);
|
|
||||||
--popover-foreground: oklch(0.2 0.012 60);
|
|
||||||
--primary: oklch(0.18 0.008 60);
|
|
||||||
--primary-foreground: oklch(0.97 0.008 80);
|
|
||||||
--secondary: oklch(0.94 0.008 75);
|
|
||||||
--secondary-foreground: oklch(0.2 0.012 60);
|
|
||||||
--muted: oklch(0.94 0.008 75);
|
|
||||||
--muted-foreground: oklch(0.5 0.015 60);
|
|
||||||
--accent: oklch(0.92 0.018 65);
|
|
||||||
--accent-foreground: oklch(0.2 0.012 60);
|
|
||||||
--destructive: oklch(0.55 0.18 25);
|
|
||||||
--destructive-foreground: oklch(0.97 0.008 80);
|
|
||||||
--border: oklch(0.88 0.01 70);
|
|
||||||
--input: oklch(0.88 0.01 70);
|
|
||||||
--ring: oklch(0.2 0.012 60);
|
|
||||||
--radius: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
--background: oklch(0.16 0.008 60);
|
|
||||||
--foreground: oklch(0.95 0.01 80);
|
|
||||||
--card: oklch(0.18 0.008 60);
|
|
||||||
--card-foreground: oklch(0.95 0.01 80);
|
|
||||||
--popover: oklch(0.18 0.008 60);
|
|
||||||
--popover-foreground: oklch(0.95 0.01 80);
|
|
||||||
--primary: oklch(0.95 0.01 80);
|
|
||||||
--primary-foreground: oklch(0.18 0.008 60);
|
|
||||||
--secondary: oklch(0.24 0.012 60);
|
|
||||||
--secondary-foreground: oklch(0.95 0.01 80);
|
|
||||||
--muted: oklch(0.24 0.012 60);
|
|
||||||
--muted-foreground: oklch(0.7 0.012 70);
|
|
||||||
--accent: oklch(0.3 0.022 65);
|
|
||||||
--accent-foreground: oklch(0.95 0.01 80);
|
|
||||||
--destructive: oklch(0.45 0.18 25);
|
|
||||||
--destructive-foreground: oklch(0.95 0.01 80);
|
|
||||||
--border: oklch(0.28 0.012 60);
|
|
||||||
--input: oklch(0.28 0.012 60);
|
|
||||||
--ring: oklch(0.85 0.012 75);
|
|
||||||
}
|
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--color-background: var(--background);
|
--color-background: var(--background);
|
||||||
--color-foreground: var(--foreground);
|
--color-foreground: var(--foreground);
|
||||||
|
|
|
||||||
50
src/themes/charcoal-cream.css
Normal file
50
src/themes/charcoal-cream.css
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* Palette: Charcoal & Cream
|
||||||
|
* High-contrast monochrome. Warm cream background, near-black warm
|
||||||
|
* charcoal ink, deep-bronze accent for the active states. The
|
||||||
|
* Asheville mood by default — moody, architectural, restrained.
|
||||||
|
* In dark mode it goes deeper still.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root[data-palette='charcoal-cream'] {
|
||||||
|
--background: oklch(0.95 0.013 75);
|
||||||
|
--foreground: oklch(0.16 0.005 60);
|
||||||
|
--card: oklch(0.95 0.013 75);
|
||||||
|
--card-foreground: oklch(0.16 0.005 60);
|
||||||
|
--popover: oklch(0.95 0.013 75);
|
||||||
|
--popover-foreground: oklch(0.16 0.005 60);
|
||||||
|
--primary: oklch(0.16 0.005 60);
|
||||||
|
--primary-foreground: oklch(0.95 0.013 75);
|
||||||
|
--secondary: oklch(0.9 0.014 75);
|
||||||
|
--secondary-foreground: oklch(0.16 0.005 60);
|
||||||
|
--muted: oklch(0.9 0.014 75);
|
||||||
|
--muted-foreground: oklch(0.45 0.012 60);
|
||||||
|
--accent: oklch(0.86 0.025 70);
|
||||||
|
--accent-foreground: oklch(0.16 0.005 60);
|
||||||
|
--destructive: oklch(0.55 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.95 0.013 75);
|
||||||
|
--border: oklch(0.82 0.014 70);
|
||||||
|
--input: oklch(0.82 0.014 70);
|
||||||
|
--ring: oklch(0.16 0.005 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-palette='charcoal-cream'].dark {
|
||||||
|
--background: oklch(0.12 0.004 60);
|
||||||
|
--foreground: oklch(0.94 0.013 75);
|
||||||
|
--card: oklch(0.14 0.004 60);
|
||||||
|
--card-foreground: oklch(0.94 0.013 75);
|
||||||
|
--popover: oklch(0.14 0.004 60);
|
||||||
|
--popover-foreground: oklch(0.94 0.013 75);
|
||||||
|
--primary: oklch(0.94 0.013 75);
|
||||||
|
--primary-foreground: oklch(0.14 0.004 60);
|
||||||
|
--secondary: oklch(0.2 0.006 60);
|
||||||
|
--secondary-foreground: oklch(0.94 0.013 75);
|
||||||
|
--muted: oklch(0.2 0.006 60);
|
||||||
|
--muted-foreground: oklch(0.68 0.012 70);
|
||||||
|
--accent: oklch(0.26 0.015 65);
|
||||||
|
--accent-foreground: oklch(0.94 0.013 75);
|
||||||
|
--destructive: oklch(0.45 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.94 0.013 75);
|
||||||
|
--border: oklch(0.24 0.008 60);
|
||||||
|
--input: oklch(0.24 0.008 60);
|
||||||
|
--ring: oklch(0.85 0.014 75);
|
||||||
|
}
|
||||||
49
src/themes/desert-clay.css
Normal file
49
src/themes/desert-clay.css
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* Palette: Desert Clay
|
||||||
|
* Warm creamy background with a terracotta undertone, espresso ink,
|
||||||
|
* burnt-clay accent. Matches Boulder's reclaimed wood / warm pendant
|
||||||
|
* mood. Reads as evening light, not gallery white.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root[data-palette='desert-clay'] {
|
||||||
|
--background: oklch(0.97 0.012 65);
|
||||||
|
--foreground: oklch(0.22 0.018 45);
|
||||||
|
--card: oklch(0.97 0.012 65);
|
||||||
|
--card-foreground: oklch(0.22 0.018 45);
|
||||||
|
--popover: oklch(0.97 0.012 65);
|
||||||
|
--popover-foreground: oklch(0.22 0.018 45);
|
||||||
|
--primary: oklch(0.4 0.07 35);
|
||||||
|
--primary-foreground: oklch(0.97 0.012 65);
|
||||||
|
--secondary: oklch(0.92 0.018 60);
|
||||||
|
--secondary-foreground: oklch(0.22 0.018 45);
|
||||||
|
--muted: oklch(0.93 0.014 60);
|
||||||
|
--muted-foreground: oklch(0.5 0.025 45);
|
||||||
|
--accent: oklch(0.86 0.04 45);
|
||||||
|
--accent-foreground: oklch(0.22 0.018 45);
|
||||||
|
--destructive: oklch(0.55 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.97 0.012 65);
|
||||||
|
--border: oklch(0.86 0.018 55);
|
||||||
|
--input: oklch(0.86 0.018 55);
|
||||||
|
--ring: oklch(0.4 0.07 35);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-palette='desert-clay'].dark {
|
||||||
|
--background: oklch(0.17 0.014 40);
|
||||||
|
--foreground: oklch(0.94 0.014 70);
|
||||||
|
--card: oklch(0.2 0.014 40);
|
||||||
|
--card-foreground: oklch(0.94 0.014 70);
|
||||||
|
--popover: oklch(0.2 0.014 40);
|
||||||
|
--popover-foreground: oklch(0.94 0.014 70);
|
||||||
|
--primary: oklch(0.85 0.05 50);
|
||||||
|
--primary-foreground: oklch(0.2 0.014 40);
|
||||||
|
--secondary: oklch(0.27 0.018 45);
|
||||||
|
--secondary-foreground: oklch(0.94 0.014 70);
|
||||||
|
--muted: oklch(0.27 0.018 45);
|
||||||
|
--muted-foreground: oklch(0.7 0.02 55);
|
||||||
|
--accent: oklch(0.34 0.045 45);
|
||||||
|
--accent-foreground: oklch(0.94 0.014 70);
|
||||||
|
--destructive: oklch(0.45 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.94 0.014 70);
|
||||||
|
--border: oklch(0.3 0.018 45);
|
||||||
|
--input: oklch(0.3 0.018 45);
|
||||||
|
--ring: oklch(0.8 0.04 50);
|
||||||
|
}
|
||||||
49
src/themes/forest-ash.css
Normal file
49
src/themes/forest-ash.css
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* Palette: Forest & Ash
|
||||||
|
* Cool sage-tinted background, charcoal ink, mossy accent. The
|
||||||
|
* "nature integrated" word from the brief made literal — picks up
|
||||||
|
* the Boulder emerald tile and the Asheville pine-window framing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root[data-palette='forest-ash'] {
|
||||||
|
--background: oklch(0.97 0.008 150);
|
||||||
|
--foreground: oklch(0.2 0.012 150);
|
||||||
|
--card: oklch(0.97 0.008 150);
|
||||||
|
--card-foreground: oklch(0.2 0.012 150);
|
||||||
|
--popover: oklch(0.97 0.008 150);
|
||||||
|
--popover-foreground: oklch(0.2 0.012 150);
|
||||||
|
--primary: oklch(0.32 0.04 150);
|
||||||
|
--primary-foreground: oklch(0.97 0.008 150);
|
||||||
|
--secondary: oklch(0.93 0.014 145);
|
||||||
|
--secondary-foreground: oklch(0.2 0.012 150);
|
||||||
|
--muted: oklch(0.93 0.012 145);
|
||||||
|
--muted-foreground: oklch(0.5 0.018 145);
|
||||||
|
--accent: oklch(0.86 0.03 150);
|
||||||
|
--accent-foreground: oklch(0.2 0.012 150);
|
||||||
|
--destructive: oklch(0.55 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.97 0.008 150);
|
||||||
|
--border: oklch(0.87 0.014 150);
|
||||||
|
--input: oklch(0.87 0.014 150);
|
||||||
|
--ring: oklch(0.32 0.04 150);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-palette='forest-ash'].dark {
|
||||||
|
--background: oklch(0.16 0.012 150);
|
||||||
|
--foreground: oklch(0.94 0.01 150);
|
||||||
|
--card: oklch(0.19 0.012 150);
|
||||||
|
--card-foreground: oklch(0.94 0.01 150);
|
||||||
|
--popover: oklch(0.19 0.012 150);
|
||||||
|
--popover-foreground: oklch(0.94 0.01 150);
|
||||||
|
--primary: oklch(0.86 0.04 150);
|
||||||
|
--primary-foreground: oklch(0.19 0.012 150);
|
||||||
|
--secondary: oklch(0.26 0.016 150);
|
||||||
|
--secondary-foreground: oklch(0.94 0.01 150);
|
||||||
|
--muted: oklch(0.26 0.016 150);
|
||||||
|
--muted-foreground: oklch(0.7 0.014 145);
|
||||||
|
--accent: oklch(0.33 0.03 150);
|
||||||
|
--accent-foreground: oklch(0.94 0.01 150);
|
||||||
|
--destructive: oklch(0.45 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.94 0.01 150);
|
||||||
|
--border: oklch(0.29 0.016 150);
|
||||||
|
--input: oklch(0.29 0.016 150);
|
||||||
|
--ring: oklch(0.8 0.04 150);
|
||||||
|
}
|
||||||
60
src/themes/index.css
Normal file
60
src/themes/index.css
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
/* Palette registry — each module declares its tokens scoped to
|
||||||
|
* :root[data-palette='<slug>']. usePalette() sets the attribute.
|
||||||
|
* A bare :root fallback below copies the stone-warm tokens so the
|
||||||
|
* page renders correctly before JS attaches the attribute and for
|
||||||
|
* users with JS disabled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import './stone-warm.css';
|
||||||
|
@import './desert-clay.css';
|
||||||
|
@import './forest-ash.css';
|
||||||
|
@import './charcoal-cream.css';
|
||||||
|
|
||||||
|
/* Pre-hydration fallback: same as stone-warm. Kept here (not in
|
||||||
|
* stone-warm.css under :root) so swapping which palette is the
|
||||||
|
* default is one edit — point this block at the values from a
|
||||||
|
* different theme module. */
|
||||||
|
:root {
|
||||||
|
--background: oklch(0.985 0.005 80);
|
||||||
|
--foreground: oklch(0.2 0.012 60);
|
||||||
|
--card: oklch(0.985 0.005 80);
|
||||||
|
--card-foreground: oklch(0.2 0.012 60);
|
||||||
|
--popover: oklch(0.985 0.005 80);
|
||||||
|
--popover-foreground: oklch(0.2 0.012 60);
|
||||||
|
--primary: oklch(0.18 0.008 60);
|
||||||
|
--primary-foreground: oklch(0.97 0.008 80);
|
||||||
|
--secondary: oklch(0.94 0.008 75);
|
||||||
|
--secondary-foreground: oklch(0.2 0.012 60);
|
||||||
|
--muted: oklch(0.94 0.008 75);
|
||||||
|
--muted-foreground: oklch(0.5 0.015 60);
|
||||||
|
--accent: oklch(0.92 0.018 65);
|
||||||
|
--accent-foreground: oklch(0.2 0.012 60);
|
||||||
|
--destructive: oklch(0.55 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.97 0.008 80);
|
||||||
|
--border: oklch(0.88 0.01 70);
|
||||||
|
--input: oklch(0.88 0.01 70);
|
||||||
|
--ring: oklch(0.2 0.012 60);
|
||||||
|
--radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: oklch(0.16 0.008 60);
|
||||||
|
--foreground: oklch(0.95 0.01 80);
|
||||||
|
--card: oklch(0.18 0.008 60);
|
||||||
|
--card-foreground: oklch(0.95 0.01 80);
|
||||||
|
--popover: oklch(0.18 0.008 60);
|
||||||
|
--popover-foreground: oklch(0.95 0.01 80);
|
||||||
|
--primary: oklch(0.95 0.01 80);
|
||||||
|
--primary-foreground: oklch(0.18 0.008 60);
|
||||||
|
--secondary: oklch(0.24 0.012 60);
|
||||||
|
--secondary-foreground: oklch(0.95 0.01 80);
|
||||||
|
--muted: oklch(0.24 0.012 60);
|
||||||
|
--muted-foreground: oklch(0.7 0.012 70);
|
||||||
|
--accent: oklch(0.3 0.022 65);
|
||||||
|
--accent-foreground: oklch(0.95 0.01 80);
|
||||||
|
--destructive: oklch(0.45 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.95 0.01 80);
|
||||||
|
--border: oklch(0.28 0.012 60);
|
||||||
|
--input: oklch(0.28 0.012 60);
|
||||||
|
--ring: oklch(0.85 0.012 75);
|
||||||
|
}
|
||||||
48
src/themes/stone-warm.css
Normal file
48
src/themes/stone-warm.css
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* Palette: Stone Warm
|
||||||
|
* Bone background, matte-black ink, taupe muted. Gallery-quiet, the
|
||||||
|
* most conservative of the four. Closest to Studio McGee's chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root[data-palette='stone-warm'] {
|
||||||
|
--background: oklch(0.985 0.005 80);
|
||||||
|
--foreground: oklch(0.2 0.012 60);
|
||||||
|
--card: oklch(0.985 0.005 80);
|
||||||
|
--card-foreground: oklch(0.2 0.012 60);
|
||||||
|
--popover: oklch(0.985 0.005 80);
|
||||||
|
--popover-foreground: oklch(0.2 0.012 60);
|
||||||
|
--primary: oklch(0.18 0.008 60);
|
||||||
|
--primary-foreground: oklch(0.97 0.008 80);
|
||||||
|
--secondary: oklch(0.94 0.008 75);
|
||||||
|
--secondary-foreground: oklch(0.2 0.012 60);
|
||||||
|
--muted: oklch(0.94 0.008 75);
|
||||||
|
--muted-foreground: oklch(0.5 0.015 60);
|
||||||
|
--accent: oklch(0.92 0.018 65);
|
||||||
|
--accent-foreground: oklch(0.2 0.012 60);
|
||||||
|
--destructive: oklch(0.55 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.97 0.008 80);
|
||||||
|
--border: oklch(0.88 0.01 70);
|
||||||
|
--input: oklch(0.88 0.01 70);
|
||||||
|
--ring: oklch(0.2 0.012 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-palette='stone-warm'].dark {
|
||||||
|
--background: oklch(0.16 0.008 60);
|
||||||
|
--foreground: oklch(0.95 0.01 80);
|
||||||
|
--card: oklch(0.18 0.008 60);
|
||||||
|
--card-foreground: oklch(0.95 0.01 80);
|
||||||
|
--popover: oklch(0.18 0.008 60);
|
||||||
|
--popover-foreground: oklch(0.95 0.01 80);
|
||||||
|
--primary: oklch(0.95 0.01 80);
|
||||||
|
--primary-foreground: oklch(0.18 0.008 60);
|
||||||
|
--secondary: oklch(0.24 0.012 60);
|
||||||
|
--secondary-foreground: oklch(0.95 0.01 80);
|
||||||
|
--muted: oklch(0.24 0.012 60);
|
||||||
|
--muted-foreground: oklch(0.7 0.012 70);
|
||||||
|
--accent: oklch(0.3 0.022 65);
|
||||||
|
--accent-foreground: oklch(0.95 0.01 80);
|
||||||
|
--destructive: oklch(0.45 0.18 25);
|
||||||
|
--destructive-foreground: oklch(0.95 0.01 80);
|
||||||
|
--border: oklch(0.28 0.012 60);
|
||||||
|
--input: oklch(0.28 0.012 60);
|
||||||
|
--ring: oklch(0.85 0.012 75);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue