New themes
This commit is contained in:
parent
be6926c027
commit
80176636b7
473
app/globals.css
473
app/globals.css
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
/* "dark:" must be true for every dark-surfaced theme, not just .dark --
|
/* "dark:" must be true for every dark-surfaced theme, not just .dark --
|
||||||
the dark looks (Dark, Ocean, Pine, Plum, Midnight, Ember, Rosewood,
|
the dark looks (Dark, Ocean, Pine, Plum, Midnight, Ember, Rosewood,
|
||||||
Cyberpunk) all turn on dark utilities. */
|
Cyberpunk, Starfield) all turn on dark utilities. */
|
||||||
@custom-variant dark (&:is(.dark *, .ocean *, .theme-pine *, .theme-plum *, .theme-midnight *, .theme-ember *, .theme-rosewood *, .theme-cyberpunk *));
|
@custom-variant dark (&:is(.dark *, .ocean *, .theme-pine *, .theme-plum *, .theme-midnight *, .theme-ember *, .theme-rosewood *, .theme-cyberpunk *, .theme-starfield *));
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--color-background: var(--background);
|
--color-background: var(--background);
|
||||||
|
|
@ -750,12 +750,152 @@
|
||||||
--sidebar-ring: oklch(0.85 0.14 195);
|
--sidebar-ring: oklch(0.85 0.14 195);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Vaporwave -- pastel synthwave: a soft pink→lavender→mint sky, a hot-magenta
|
||||||
|
action color, an electric-cyan focus, and a rounded retro face (Righteous).
|
||||||
|
Light-surfaced; see the extras section for the pastel sky, the synthwave
|
||||||
|
sun, the soft glow, and the to-do treatment. */
|
||||||
|
.theme-vaporwave {
|
||||||
|
color-scheme: light;
|
||||||
|
--background: oklch(0.92 0.045 320);
|
||||||
|
--foreground: oklch(0.32 0.09 335);
|
||||||
|
--card: oklch(0.972 0.012 330);
|
||||||
|
--card-foreground: oklch(0.32 0.09 335);
|
||||||
|
--popover: oklch(0.972 0.012 330);
|
||||||
|
--popover-foreground: oklch(0.32 0.09 335);
|
||||||
|
/* Hot magenta -- deep enough for a clean, WCAG-AA white label. */
|
||||||
|
--primary: oklch(0.56 0.26 350);
|
||||||
|
--primary-foreground: oklch(0.99 0 0);
|
||||||
|
--secondary: oklch(0.9 0.045 325);
|
||||||
|
--secondary-foreground: oklch(0.34 0.09 335);
|
||||||
|
--muted: oklch(0.925 0.025 325);
|
||||||
|
--muted-foreground: oklch(0.47 0.08 335);
|
||||||
|
/* A cool mint accent so the hover state isn't just more pink. */
|
||||||
|
--accent: oklch(0.89 0.055 200);
|
||||||
|
--accent-foreground: oklch(0.3 0.09 200);
|
||||||
|
--destructive: oklch(0.58 0.21 25);
|
||||||
|
--destructive-foreground: oklch(0.99 0 0);
|
||||||
|
--border: oklch(0.8 0.055 325);
|
||||||
|
--input: oklch(0.8 0.055 325);
|
||||||
|
/* Electric-cyan focus ring. */
|
||||||
|
--ring: oklch(0.56 0.19 195);
|
||||||
|
--lane: oklch(1 0 0 / 6%);
|
||||||
|
--chart-1: oklch(0.6 0.24 350);
|
||||||
|
--chart-2: oklch(0.62 0.2 300);
|
||||||
|
--chart-3: oklch(0.62 0.18 200);
|
||||||
|
--chart-4: oklch(0.66 0.16 160);
|
||||||
|
--chart-5: oklch(0.72 0.15 90);
|
||||||
|
/* Soft, chrome-rounded corners. */
|
||||||
|
--radius: 0.85rem;
|
||||||
|
--sidebar: oklch(0.89 0.05 325);
|
||||||
|
--sidebar-foreground: oklch(0.32 0.09 335);
|
||||||
|
--sidebar-primary: oklch(0.56 0.26 350);
|
||||||
|
--sidebar-primary-foreground: oklch(0.99 0 0);
|
||||||
|
--sidebar-accent: oklch(0.85 0.065 325);
|
||||||
|
--sidebar-accent-foreground: oklch(0.34 0.09 335);
|
||||||
|
--sidebar-border: oklch(0.8 0.055 325);
|
||||||
|
--sidebar-ring: oklch(0.56 0.19 195);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Starfield -- deep space: near-black indigo, a warm star-gold action color,
|
||||||
|
a bright-cyan focus, and a sci-fi face (Orbitron). Dark-surfaced; see the
|
||||||
|
extras section for the starfield, the nebula glow, and the to-do treatment.
|
||||||
|
*/
|
||||||
|
.theme-starfield {
|
||||||
|
color-scheme: dark;
|
||||||
|
--background: oklch(0.14 0.035 270);
|
||||||
|
--foreground: oklch(0.9 0.025 250);
|
||||||
|
--card: oklch(0.185 0.04 270);
|
||||||
|
--card-foreground: oklch(0.9 0.025 250);
|
||||||
|
--popover: oklch(0.2 0.045 270);
|
||||||
|
--popover-foreground: oklch(0.9 0.025 250);
|
||||||
|
/* Star-gold -- a warm light against the cold void; carries dark ink. */
|
||||||
|
--primary: oklch(0.78 0.15 82);
|
||||||
|
--primary-foreground: oklch(0.19 0.04 270);
|
||||||
|
--secondary: oklch(0.24 0.05 270);
|
||||||
|
--secondary-foreground: oklch(0.88 0.04 250);
|
||||||
|
--muted: oklch(0.21 0.045 270);
|
||||||
|
--muted-foreground: oklch(0.7 0.035 255);
|
||||||
|
--accent: oklch(0.27 0.06 270);
|
||||||
|
--accent-foreground: oklch(0.9 0.04 250);
|
||||||
|
--destructive: oklch(0.56 0.21 25);
|
||||||
|
--destructive-foreground: oklch(0.99 0 0);
|
||||||
|
--border: oklch(0.9 0.04 250 / 16%);
|
||||||
|
--input: oklch(0.9 0.04 250 / 13%);
|
||||||
|
/* Bright-cyan focus. */
|
||||||
|
--ring: oklch(0.78 0.15 210);
|
||||||
|
--lane: oklch(1 0 0 / 5%);
|
||||||
|
--chart-1: oklch(0.78 0.15 210);
|
||||||
|
--chart-2: oklch(0.72 0.16 82);
|
||||||
|
--chart-3: oklch(0.7 0.16 290);
|
||||||
|
--chart-4: oklch(0.74 0.14 160);
|
||||||
|
--chart-5: oklch(0.8 0.12 30);
|
||||||
|
/* Medium, calm corners. */
|
||||||
|
--radius: 0.7rem;
|
||||||
|
--sidebar: oklch(0.165 0.042 270);
|
||||||
|
--sidebar-foreground: oklch(0.9 0.025 250);
|
||||||
|
--sidebar-primary: oklch(0.78 0.15 82);
|
||||||
|
--sidebar-primary-foreground: oklch(0.19 0.04 270);
|
||||||
|
--sidebar-accent: oklch(0.27 0.06 270);
|
||||||
|
--sidebar-accent-foreground: oklch(0.9 0.04 250);
|
||||||
|
--sidebar-border: oklch(0.9 0.04 250 / 16%);
|
||||||
|
--sidebar-ring: oklch(0.78 0.15 210);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notebook -- stationery: a warm desk tone, white ruled-paper cards, a blue
|
||||||
|
ballpoint action color, a red margin rule, and a casual handwriting face
|
||||||
|
(Caveat). Light-surfaced; see the extras section for the ruled paper, the
|
||||||
|
margin line, and the highlighter to-do treatment. */
|
||||||
|
.theme-notebook {
|
||||||
|
color-scheme: light;
|
||||||
|
--background: oklch(0.86 0.025 80);
|
||||||
|
--foreground: oklch(0.25 0.025 70);
|
||||||
|
--card: oklch(0.978 0.008 90);
|
||||||
|
--card-foreground: oklch(0.25 0.025 70);
|
||||||
|
--popover: oklch(0.978 0.008 90);
|
||||||
|
--popover-foreground: oklch(0.25 0.025 70);
|
||||||
|
/* Blue ballpoint ink -- deep enough for a clean white label. */
|
||||||
|
--primary: oklch(0.46 0.13 255);
|
||||||
|
--primary-foreground: oklch(0.99 0 0);
|
||||||
|
--secondary: oklch(0.9 0.025 250);
|
||||||
|
--secondary-foreground: oklch(0.28 0.03 250);
|
||||||
|
--muted: oklch(0.93 0.012 90);
|
||||||
|
--muted-foreground: oklch(0.44 0.035 75);
|
||||||
|
/* A light blue, like a page highlight. */
|
||||||
|
--accent: oklch(0.89 0.045 250);
|
||||||
|
--accent-foreground: oklch(0.3 0.05 250);
|
||||||
|
--destructive: oklch(0.57 0.21 25);
|
||||||
|
--destructive-foreground: oklch(0.99 0 0);
|
||||||
|
/* A pale blue rule line. */
|
||||||
|
--border: oklch(0.79 0.035 250);
|
||||||
|
--input: oklch(0.79 0.035 250);
|
||||||
|
/* Blue-ink focus. */
|
||||||
|
--ring: oklch(0.5 0.15 255);
|
||||||
|
--lane: oklch(1 0 0 / 5%);
|
||||||
|
--chart-1: oklch(0.5 0.13 255);
|
||||||
|
--chart-2: oklch(0.55 0.14 190);
|
||||||
|
--chart-3: oklch(0.6 0.13 80);
|
||||||
|
--chart-4: oklch(0.55 0.18 25);
|
||||||
|
--chart-5: oklch(0.58 0.14 130);
|
||||||
|
/* Slightly rounded paper corners. */
|
||||||
|
--radius: 0.6rem;
|
||||||
|
--sidebar: oklch(0.83 0.028 80);
|
||||||
|
--sidebar-foreground: oklch(0.25 0.025 70);
|
||||||
|
--sidebar-primary: oklch(0.46 0.13 255);
|
||||||
|
--sidebar-primary-foreground: oklch(0.99 0 0);
|
||||||
|
--sidebar-accent: oklch(0.85 0.05 250);
|
||||||
|
--sidebar-accent-foreground: oklch(0.28 0.04 250);
|
||||||
|
--sidebar-border: oklch(0.78 0.035 250);
|
||||||
|
--sidebar-ring: oklch(0.5 0.15 255);
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------
|
||||||
EXTRA THEMES -- beyond tokens, Blueprint and Cyberpunk carry their own
|
EXTRA THEMES -- beyond tokens, Blueprint, Cyberpunk, Vaporwave, Starfield,
|
||||||
fonts, backgrounds, and animations. Everything here is scoped under the
|
and Notebook each carry their own fonts, backgrounds, and animations.
|
||||||
theme's own class on <html>, so no other theme is touched. The reduced-
|
Everything here is scoped under the theme's own class on <html>, so no
|
||||||
motion guard in @layer base still kills the animations for users who
|
other theme is touched. The reduced-motion guard in @layer base still
|
||||||
ask for it (the static styling remains).
|
kills the animations for users who ask for it (the static styling remains).
|
||||||
|
All the corner character comes from each theme's `--radius` token (the
|
||||||
|
`rounded-*` utilities scale from it), so no per-theme corner overrides.
|
||||||
--------------------------------------------------------------------------- */
|
--------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* ------------------------------ Blueprint -------------------------------- */
|
/* ------------------------------ Blueprint -------------------------------- */
|
||||||
|
|
@ -1152,8 +1292,10 @@ html.theme-cyberpunk [data-todo-checkbox] svg {
|
||||||
filter: drop-shadow(0 0 3px rgb(34 255 238 / 0.85));
|
filter: drop-shadow(0 0 3px rgb(34 255 238 / 0.85));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The whole card glitches every so often -- a brief RGB-split, a skew, and a
|
/* The whole card glitches every so often -- a brief RGB-split, a move, and a
|
||||||
sliced clip, then it settles back. Most of the cycle is calm; the burst is a
|
skew, then it settles back. No clip-path: the card never gets sliced away,
|
||||||
|
it only jitters, skews, and throws a chromatic fringe, so the whole thing
|
||||||
|
stays visible the whole time. Most of the cycle is calm; the burst is a
|
||||||
handful of held frames (steps, so it jitters rather than eases). Cards are
|
handful of held frames (steps, so it jitters rather than eases). Cards are
|
||||||
phase-offset so a boardful of them don't all tear on the same beat. */
|
phase-offset so a boardful of them don't all tear on the same beat. */
|
||||||
html.theme-cyberpunk [data-group-card] {
|
html.theme-cyberpunk [data-group-card] {
|
||||||
|
|
@ -1183,16 +1325,18 @@ html.theme-cyberpunk [data-group-card]:nth-child(3n) {
|
||||||
}
|
}
|
||||||
88% {
|
88% {
|
||||||
transform: translate(3px, -1px);
|
transform: translate(3px, -1px);
|
||||||
clip-path: inset(0 0 14% 0);
|
|
||||||
filter: saturate(1.8);
|
filter: saturate(1.8);
|
||||||
|
box-shadow:
|
||||||
|
-3px 0 rgb(255 43 214 / 0.55),
|
||||||
|
3px 0 rgb(34 255 238 / 0.55);
|
||||||
}
|
}
|
||||||
89% {
|
89% {
|
||||||
transform: translate(-1px, 1px) skewX(2deg);
|
transform: translate(-1px, 1px) skewX(2deg);
|
||||||
clip-path: inset(12% 0 0 0);
|
filter: hue-rotate(14deg) saturate(1.5);
|
||||||
}
|
}
|
||||||
90% {
|
90% {
|
||||||
transform: translate(2px, -1px);
|
transform: translate(2px, -1px);
|
||||||
clip-path: inset(6% 0 18% 0);
|
filter: saturate(1.4);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
-4px 0 rgb(255 43 214 / 0.5),
|
-4px 0 rgb(255 43 214 / 0.5),
|
||||||
4px 0 rgb(34 255 238 / 0.5);
|
4px 0 rgb(34 255 238 / 0.5);
|
||||||
|
|
@ -1207,6 +1351,311 @@ html.theme-cyberpunk [data-group-card]:nth-child(3n) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------ Vaporwave ------------------------------- */
|
||||||
|
|
||||||
|
/* The retro face carries the whole deck: Righteous (a rounded, retro-futur-
|
||||||
|
istic face) for headings AND for the body/to-do text, so everything reads
|
||||||
|
like a glossy 90s desktop, not just the title. Retarget the theme's font
|
||||||
|
variables so every `font-sans` surface (to-dos, buttons, nav, note editor)
|
||||||
|
and every `font-heading` title picks it up. */
|
||||||
|
html.theme-vaporwave {
|
||||||
|
--font-sans: var(--font-vaporwave), "Trebuchet MS", "Segoe UI", sans-serif;
|
||||||
|
--font-heading: var(--font-vaporwave), "Trebuchet MS", "Segoe UI", sans-serif;
|
||||||
|
}
|
||||||
|
/* Righteous already runs a touch wide; a hair of tracking reads cleaner. */
|
||||||
|
html.theme-vaporwave .font-heading {
|
||||||
|
letter-spacing: 0.015em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pastel sky: a soft pink→lavender→mint wash, with a warm sunrise glow
|
||||||
|
bleeding down from the top. Sits on the token's background color. */
|
||||||
|
html.theme-vaporwave body {
|
||||||
|
background-image:
|
||||||
|
radial-gradient(
|
||||||
|
120% 55% at 50% -12%,
|
||||||
|
oklch(0.9 0.26 25 / 0.4) 0%,
|
||||||
|
oklch(0.9 0.24 345 / 0.22) 34%,
|
||||||
|
transparent 62%
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
180deg,
|
||||||
|
oklch(0.9 0.075 322) 0%,
|
||||||
|
oklch(0.945 0.05 292) 46%,
|
||||||
|
oklch(0.955 0.055 190) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/* Faint scanlines rolling slowly, like a monitor left on in the morning. */
|
||||||
|
html.theme-vaporwave body::before {
|
||||||
|
content: "";
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
background-image: repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
oklch(0.42 0.16 320 / 0.035) 0px,
|
||||||
|
oklch(0.42 0.16 320 / 0.035) 1px,
|
||||||
|
transparent 1px,
|
||||||
|
transparent 4px
|
||||||
|
);
|
||||||
|
animation: vw-roll 16s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes vw-roll {
|
||||||
|
from {
|
||||||
|
background-position-y: 0px;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-position-y: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Primary blooms with a soft magenta glow; focus glows electric cyan. */
|
||||||
|
html.theme-vaporwave .bg-primary {
|
||||||
|
box-shadow: 0 4px 18px oklch(0.62 0.25 350 / 0.35);
|
||||||
|
}
|
||||||
|
html.theme-vaporwave :focus-visible {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 3px color-mix(in oklch, var(--ring) 40%, transparent),
|
||||||
|
0 0 14px oklch(0.56 0.19 195 / 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To-do checkbox: rounded (the chrome look), a cyan glow that builds on
|
||||||
|
hover, and a magenta bloom the moment it's checked. (The check's own
|
||||||
|
stroke/fill already come from the group's accent color.) */
|
||||||
|
html.theme-vaporwave [data-todo-checkbox] {
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
html.theme-vaporwave [data-todo-checkbox]:hover {
|
||||||
|
box-shadow: 0 0 10px oklch(0.56 0.19 195 / 0.5);
|
||||||
|
}
|
||||||
|
html.theme-vaporwave [data-todo-checkbox][aria-checked="true"] {
|
||||||
|
box-shadow: 0 0 12px oklch(0.62 0.25 350 / 0.55);
|
||||||
|
}
|
||||||
|
html.theme-vaporwave [data-todo-checkbox] svg {
|
||||||
|
filter: drop-shadow(0 0 3px oklch(0.56 0.19 195 / 0.8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completed to-do: the strike flickers with a soft neon glow before it
|
||||||
|
settles, like a sign powering down. */
|
||||||
|
html.theme-vaporwave .line-through {
|
||||||
|
text-decoration-thickness: 1.5px;
|
||||||
|
animation: vw-flicker 420ms steps(6, jump-none) 1;
|
||||||
|
}
|
||||||
|
@keyframes vw-flicker {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
20% {
|
||||||
|
text-shadow: 0 0 8px oklch(0.62 0.25 350 / 0.7);
|
||||||
|
}
|
||||||
|
45% {
|
||||||
|
text-shadow: 0 0 3px oklch(0.56 0.19 195 / 0.6);
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
text-shadow: 0 0 6px oklch(0.62 0.25 350 / 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------- Starfield ------------------------------ */
|
||||||
|
|
||||||
|
/* The sci-fi face carries the whole deck: Orbitron (a geometric, techy face)
|
||||||
|
for headings AND for the body/to-do text, so everything reads like a ship
|
||||||
|
console. Retarget the theme's font variables. */
|
||||||
|
html.theme-starfield {
|
||||||
|
--font-sans: var(--font-starfield), "Segoe UI", system-ui, sans-serif;
|
||||||
|
--font-heading: var(--font-starfield), "Segoe UI", system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
/* Orbitron is wide and angular; a touch of tracking sells the console feel. */
|
||||||
|
html.theme-starfield .font-heading {
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The void: a deep indigo nebula fading to near-black at the edges. */
|
||||||
|
html.theme-starfield body {
|
||||||
|
background-image: radial-gradient(
|
||||||
|
120% 100% at 50% 0%,
|
||||||
|
oklch(0.23 0.08 272) 0%,
|
||||||
|
oklch(0.16 0.05 268) 55%,
|
||||||
|
oklch(0.12 0.04 262) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A starfield: a tiled field of small stars at a couple of sizes/temperatures,
|
||||||
|
sitting behind the content (stars show in the void between surfaces). A
|
||||||
|
slow twinkle keeps it alive. */
|
||||||
|
html.theme-starfield body::before {
|
||||||
|
content: "";
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
background-image:
|
||||||
|
radial-gradient(1px 1px at 20px 30px, oklch(0.98 0 0 / 0.95), transparent),
|
||||||
|
radial-gradient(1px 1px at 140px 110px, oklch(0.94 0.03 210 / 0.75), transparent),
|
||||||
|
radial-gradient(1.5px 1.5px at 230px 180px, oklch(0.9 0.06 85 / 0.7), transparent),
|
||||||
|
radial-gradient(1px 1px at 90px 210px, oklch(0.88 0.05 300 / 0.55), transparent),
|
||||||
|
radial-gradient(2px 2px at 200px 60px, oklch(0.96 0.02 210 / 0.5), transparent);
|
||||||
|
background-size: 280px 280px;
|
||||||
|
animation: sf-twinkle 7s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes sf-twinkle {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* The odd shooting star streaking across the void. */
|
||||||
|
html.theme-starfield body::after {
|
||||||
|
content: "";
|
||||||
|
position: fixed;
|
||||||
|
top: 14%;
|
||||||
|
left: -8%;
|
||||||
|
width: 110px;
|
||||||
|
height: 1.5px;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: linear-gradient(90deg, transparent, oklch(0.98 0 0 / 0.9));
|
||||||
|
opacity: 0;
|
||||||
|
animation: sf-shoot 13s ease-in 3s infinite;
|
||||||
|
}
|
||||||
|
@keyframes sf-shoot {
|
||||||
|
0% {
|
||||||
|
transform: translate(0, 0) rotate(-9deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
3% {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
11% {
|
||||||
|
transform: translate(64vw, 9vh) rotate(-9deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Star-gold primary blooms; focus glows bright cyan. */
|
||||||
|
html.theme-starfield .bg-primary {
|
||||||
|
box-shadow: 0 0 16px oklch(0.78 0.15 82 / 0.32);
|
||||||
|
}
|
||||||
|
html.theme-starfield :focus-visible {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 3px color-mix(in oklch, var(--ring) 40%, transparent),
|
||||||
|
0 0 14px oklch(0.78 0.15 210 / 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To-do checkbox: a crisp console box; a cyan glow builds on hover and blooms
|
||||||
|
when checked. (The check's own stroke/fill already come from the group's
|
||||||
|
accent color.) */
|
||||||
|
html.theme-starfield [data-todo-checkbox] {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
html.theme-starfield [data-todo-checkbox]:hover {
|
||||||
|
box-shadow: 0 0 10px oklch(0.78 0.15 210 / 0.5);
|
||||||
|
}
|
||||||
|
html.theme-starfield [data-todo-checkbox][aria-checked="true"] {
|
||||||
|
box-shadow: 0 0 12px oklch(0.78 0.15 210 / 0.6);
|
||||||
|
}
|
||||||
|
html.theme-starfield [data-todo-checkbox] svg {
|
||||||
|
filter: drop-shadow(0 0 3px oklch(0.78 0.15 210 / 0.85));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A completed to-do keeps a faint star-glow on its strike, like a name lit up
|
||||||
|
against the dark. */
|
||||||
|
html.theme-starfield .line-through {
|
||||||
|
text-decoration-thickness: 1.5px;
|
||||||
|
text-shadow: 0 0 8px oklch(0.9 0.1 85 / 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------- Notebook ------------------------------- */
|
||||||
|
|
||||||
|
/* The pen script carries the whole deck: Caveat (a casual handwriting face)
|
||||||
|
for headings AND for the body/to-do text, so everything reads as written by
|
||||||
|
hand. Retarget the theme's font variables. Caveat runs light at small
|
||||||
|
sizes, so give the body a touch of weight. */
|
||||||
|
html.theme-notebook {
|
||||||
|
--font-sans: var(--font-notebook), "Segoe Print", "Bradley Hand", cursive;
|
||||||
|
--font-heading: var(--font-notebook), "Segoe Print", "Bradley Hand", cursive;
|
||||||
|
}
|
||||||
|
html.theme-notebook body {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
html.theme-notebook .font-heading {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
/* A handwriting face crowds under the base's tight tracking -- relax it. */
|
||||||
|
html.theme-notebook body,
|
||||||
|
html.theme-notebook h1,
|
||||||
|
html.theme-notebook h2,
|
||||||
|
html.theme-notebook h3,
|
||||||
|
html.theme-notebook h4 {
|
||||||
|
letter-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Warm desk: the paper cards read as sheets laid on a worktop. */
|
||||||
|
html.theme-notebook body {
|
||||||
|
background-image: linear-gradient(180deg, oklch(0.88 0.024 82), oklch(0.84 0.028 80));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ruled paper on the white card surfaces: blue rules + a red margin line on
|
||||||
|
the left, the classic notebook page. */
|
||||||
|
html.theme-notebook [data-slot="card"],
|
||||||
|
html.theme-notebook [data-slot="dialog-content"] {
|
||||||
|
background-image:
|
||||||
|
linear-gradient(90deg, transparent 24px, oklch(0.6 0.19 25 / 0.4) 24px 26px, transparent 26px),
|
||||||
|
repeating-linear-gradient(180deg, transparent 0 27px, oklch(0.68 0.09 250 / 0.4) 27px 28px);
|
||||||
|
}
|
||||||
|
/* Group cards keep their own pastel tint (they read as index cards) but carry
|
||||||
|
a faint red margin line so they stay in the stationery family. */
|
||||||
|
html.theme-notebook [data-group-card] {
|
||||||
|
background-image: linear-gradient(90deg, transparent 20px, oklch(0.6 0.19 25 / 0.3) 20px 22px, transparent 22px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blue-ink focus. */
|
||||||
|
html.theme-notebook .bg-primary {
|
||||||
|
box-shadow: 0 3px 14px oklch(0.46 0.13 255 / 0.28);
|
||||||
|
}
|
||||||
|
html.theme-notebook :focus-visible {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 3px color-mix(in oklch, var(--ring) 35%, transparent),
|
||||||
|
0 0 12px oklch(0.5 0.15 255 / 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To-do checkbox: a printed box with a blue-ink stroke; a highlighter glow
|
||||||
|
builds on hover and marks the checked box. (The check's own stroke/fill
|
||||||
|
already come from the group's accent color.) */
|
||||||
|
html.theme-notebook [data-todo-checkbox] {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
html.theme-notebook [data-todo-checkbox]:hover {
|
||||||
|
box-shadow: 0 0 0 3px oklch(0.9 0.17 105 / 0.5);
|
||||||
|
}
|
||||||
|
html.theme-notebook [data-todo-checkbox][aria-checked="true"] {
|
||||||
|
box-shadow: 0 0 0 3px oklch(0.9 0.17 105 / 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completed to-do: a highlighter sweeps under the words, then the pen strikes
|
||||||
|
through -- the classic "done it, now cross it out" note. */
|
||||||
|
html.theme-notebook .line-through {
|
||||||
|
text-decoration-thickness: 1.5px;
|
||||||
|
background-image: linear-gradient(0deg, oklch(0.93 0.19 105 / 0.4) 0 100%);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 0% 60%;
|
||||||
|
background-position: 0 62%;
|
||||||
|
animation: nb-highlight 420ms ease-out forwards;
|
||||||
|
}
|
||||||
|
@keyframes nb-highlight {
|
||||||
|
to {
|
||||||
|
background-size: 100% 60%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@apply border-border outline-ring/50;
|
@apply border-border outline-ring/50;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,14 @@
|
||||||
import type { Metadata, Viewport } from "next";
|
import type { Metadata, Viewport } from "next";
|
||||||
import { Architects_Daughter, Figtree, Inter, JetBrains_Mono, VT323 } from "next/font/google";
|
import {
|
||||||
|
Architects_Daughter,
|
||||||
|
Caveat,
|
||||||
|
Figtree,
|
||||||
|
Inter,
|
||||||
|
JetBrains_Mono,
|
||||||
|
Orbitron,
|
||||||
|
Righteous,
|
||||||
|
VT323,
|
||||||
|
} from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
import { ThemeProvider } from "@/components/theme/theme-provider";
|
import { ThemeProvider } from "@/components/theme/theme-provider";
|
||||||
|
|
@ -42,6 +51,27 @@ const vt323 = VT323({
|
||||||
weight: "400",
|
weight: "400",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** Vaporwave theme's retro face (see app/globals.css) -- a rounded,
|
||||||
|
* retro-futuristic face for the pastel synthwave look. */
|
||||||
|
const righteous = Righteous({
|
||||||
|
variable: "--font-vaporwave",
|
||||||
|
subsets: ["latin"],
|
||||||
|
weight: "400",
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Starfield theme's sci-fi face (see app/globals.css). */
|
||||||
|
const orbitron = Orbitron({
|
||||||
|
variable: "--font-starfield",
|
||||||
|
subsets: ["latin"],
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Notebook theme's handwriting face (see app/globals.css) -- a casual pen
|
||||||
|
* script for the stationery look. */
|
||||||
|
const caveat = Caveat({
|
||||||
|
variable: "--font-notebook",
|
||||||
|
subsets: ["latin"],
|
||||||
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Organize",
|
title: "Organize",
|
||||||
description: "An extended to-do list and notes organizer.",
|
description: "An extended to-do list and notes organizer.",
|
||||||
|
|
@ -68,21 +98,22 @@ export default function RootLayout({ children }: LayoutProps<"/">) {
|
||||||
return (
|
return (
|
||||||
<html
|
<html
|
||||||
lang="en"
|
lang="en"
|
||||||
className={`${inter.variable} ${figtree.variable} ${jetbrainsMono.variable} ${architectsDaughter.variable} ${vt323.variable} h-full antialiased`}
|
className={`${inter.variable} ${figtree.variable} ${jetbrainsMono.variable} ${architectsDaughter.variable} ${vt323.variable} ${righteous.variable} ${orbitron.variable} ${caveat.variable} h-full antialiased`}
|
||||||
suppressHydrationWarning
|
suppressHydrationWarning
|
||||||
>
|
>
|
||||||
<body className="min-h-full flex flex-col">
|
<body className="min-h-full flex flex-col">
|
||||||
{/* Sixteen looks: eight light (Default, Sunset, Meadow, Honey, Rosé,
|
{/* Nineteen looks: ten light (Default, Sunset, Meadow, Honey, Rosé,
|
||||||
Lavender, Slate, Blueprint) and eight dark (Dark, Ocean, Pine,
|
Lavender, Slate, Blueprint, Vaporwave, Notebook) and nine dark
|
||||||
Plum, Midnight, Ember, Rosewood, Cyberpunk) -- complete token
|
(Dark, Ocean, Pine, Plum, Midnight, Ember, Rosewood, Cyberpunk,
|
||||||
sets in app/globals.css; Blueprint and Cyberpunk additionally
|
Starfield) -- complete token sets in app/globals.css; Blueprint,
|
||||||
carry their own fonts, backgrounds, and animations.
|
Cyberpunk, Vaporwave, Starfield, and Notebook additionally carry
|
||||||
|
their own fonts, backgrounds, and animations.
|
||||||
"system" resolves to Default/Dark by OS preference.
|
"system" resolves to Default/Dark by OS preference.
|
||||||
No-FOUC theme restore: runs before first paint, applies the
|
No-FOUC theme restore: runs before first paint, applies the
|
||||||
stored preference to <html> (class + color-scheme). */}
|
stored preference to <html> (class + color-scheme). */}
|
||||||
<script
|
<script
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: `!(function(){try{var r=document.documentElement,c=['theme-default','theme-sunset','theme-meadow','theme-honey','theme-rose','theme-lavender','theme-slate','theme-blueprint','dark','ocean','theme-pine','theme-plum','theme-midnight','theme-ember','theme-rosewood','theme-cyberpunk','light'];for(var i=0;i<c.length;i++){r.classList.remove(c[i]);}var v=null;try{v=localStorage.getItem('theme');}catch(e){}var m={default:'theme-default',sunset:'theme-sunset',meadow:'theme-meadow',honey:'theme-honey',rose:'theme-rose',lavender:'theme-lavender',slate:'theme-slate',blueprint:'theme-blueprint',dark:'dark',ocean:'ocean',pine:'theme-pine',plum:'theme-plum',midnight:'theme-midnight',ember:'theme-ember',rosewood:'theme-rosewood',cyberpunk:'theme-cyberpunk'};var d=['dark','ocean','pine','plum','midnight','ember','rosewood','cyberpunk'];if(v==='system'||!v){v=window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'default';}if(m[v]){r.classList.add(m[v]);r.style.colorScheme=d.indexOf(v)>=0?'dark':'light';}}catch(e){}})();`,
|
__html: `!(function(){try{var r=document.documentElement,c=['theme-default','theme-sunset','theme-meadow','theme-honey','theme-rose','theme-lavender','theme-slate','theme-blueprint','theme-vaporwave','theme-notebook','dark','ocean','theme-pine','theme-plum','theme-midnight','theme-ember','theme-rosewood','theme-cyberpunk','theme-starfield','light'];for(var i=0;i<c.length;i++){r.classList.remove(c[i]);}var v=null;try{v=localStorage.getItem('theme');}catch(e){}var m={default:'theme-default',sunset:'theme-sunset',meadow:'theme-meadow',honey:'theme-honey',rose:'theme-rose',lavender:'theme-lavender',slate:'theme-slate',blueprint:'theme-blueprint',vaporwave:'theme-vaporwave',notebook:'theme-notebook',dark:'dark',ocean:'ocean',pine:'theme-pine',plum:'theme-plum',midnight:'theme-midnight',ember:'theme-ember',rosewood:'theme-rosewood',cyberpunk:'theme-cyberpunk',starfield:'theme-starfield'};var d=['dark','ocean','pine','plum','midnight','ember','rosewood','cyberpunk','starfield'];if(v==='system'||!v){v=window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'default';}if(m[v]){r.classList.add(m[v]);r.style.colorScheme=d.indexOf(v)>=0?'dark':'light';}}catch(e){}})();`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ThemeProvider defaultTheme="system">
|
<ThemeProvider defaultTheme="system">
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ export const THEMES = [
|
||||||
"lavender",
|
"lavender",
|
||||||
"slate",
|
"slate",
|
||||||
"blueprint",
|
"blueprint",
|
||||||
|
"vaporwave",
|
||||||
|
"notebook",
|
||||||
"dark",
|
"dark",
|
||||||
"ocean",
|
"ocean",
|
||||||
"pine",
|
"pine",
|
||||||
|
|
@ -46,6 +48,7 @@ export const THEMES = [
|
||||||
"ember",
|
"ember",
|
||||||
"rosewood",
|
"rosewood",
|
||||||
"cyberpunk",
|
"cyberpunk",
|
||||||
|
"starfield",
|
||||||
] as const;
|
] as const;
|
||||||
export type ThemeName = (typeof THEMES)[number];
|
export type ThemeName = (typeof THEMES)[number];
|
||||||
export type RawTheme = ThemeName | "system";
|
export type RawTheme = ThemeName | "system";
|
||||||
|
|
@ -60,6 +63,8 @@ const THEME_CLASSES: Record<ThemeName, string> = {
|
||||||
lavender: "theme-lavender",
|
lavender: "theme-lavender",
|
||||||
slate: "theme-slate",
|
slate: "theme-slate",
|
||||||
blueprint: "theme-blueprint",
|
blueprint: "theme-blueprint",
|
||||||
|
vaporwave: "theme-vaporwave",
|
||||||
|
notebook: "theme-notebook",
|
||||||
dark: "dark",
|
dark: "dark",
|
||||||
ocean: "ocean",
|
ocean: "ocean",
|
||||||
pine: "theme-pine",
|
pine: "theme-pine",
|
||||||
|
|
@ -68,6 +73,7 @@ const THEME_CLASSES: Record<ThemeName, string> = {
|
||||||
ember: "theme-ember",
|
ember: "theme-ember",
|
||||||
rosewood: "theme-rosewood",
|
rosewood: "theme-rosewood",
|
||||||
cyberpunk: "theme-cyberpunk",
|
cyberpunk: "theme-cyberpunk",
|
||||||
|
starfield: "theme-starfield",
|
||||||
};
|
};
|
||||||
const ALL_CLASSES = Object.values(THEME_CLASSES);
|
const ALL_CLASSES = Object.values(THEME_CLASSES);
|
||||||
/* Themes whose *surfaces* are dark (see app/globals.css). The single source
|
/* Themes whose *surfaces* are dark (see app/globals.css). The single source
|
||||||
|
|
@ -82,6 +88,7 @@ export const DARK_SURFACES: ThemeName[] = [
|
||||||
"ember",
|
"ember",
|
||||||
"rosewood",
|
"rosewood",
|
||||||
"cyberpunk",
|
"cyberpunk",
|
||||||
|
"starfield",
|
||||||
];
|
];
|
||||||
|
|
||||||
interface ThemeContextValue {
|
interface ThemeContextValue {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ import {
|
||||||
Wine,
|
Wine,
|
||||||
DraftingCompass,
|
DraftingCompass,
|
||||||
CircuitBoard,
|
CircuitBoard,
|
||||||
|
Disc3,
|
||||||
|
Orbit,
|
||||||
|
NotebookText,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
import { useTheme } from "@/components/theme/theme-provider";
|
import { useTheme } from "@/components/theme/theme-provider";
|
||||||
|
|
@ -52,6 +55,8 @@ const LIGHT_OPTIONS: ThemeOption[] = [
|
||||||
{ value: "lavender", label: "Lavender", icon: Flower2, swatch: "#7c3aed" },
|
{ value: "lavender", label: "Lavender", icon: Flower2, swatch: "#7c3aed" },
|
||||||
{ value: "slate", label: "Slate", icon: Mountain, swatch: "#4a6d9c" },
|
{ value: "slate", label: "Slate", icon: Mountain, swatch: "#4a6d9c" },
|
||||||
{ value: "blueprint", label: "Blueprint", icon: DraftingCompass, swatch: "#2b4bc4" },
|
{ value: "blueprint", label: "Blueprint", icon: DraftingCompass, swatch: "#2b4bc4" },
|
||||||
|
{ value: "vaporwave", label: "Vaporwave", icon: Disc3, swatch: "#e879f9" },
|
||||||
|
{ value: "notebook", label: "Notebook", icon: NotebookText, swatch: "#3b5fc4" },
|
||||||
];
|
];
|
||||||
const DARK_OPTIONS: ThemeOption[] = [
|
const DARK_OPTIONS: ThemeOption[] = [
|
||||||
{ value: "dark", label: "Dark", icon: Moon, swatch: "#7c83f2" },
|
{ value: "dark", label: "Dark", icon: Moon, swatch: "#7c83f2" },
|
||||||
|
|
@ -62,6 +67,7 @@ const DARK_OPTIONS: ThemeOption[] = [
|
||||||
{ value: "ember", label: "Ember", icon: Flame, swatch: "#fbbf24" },
|
{ value: "ember", label: "Ember", icon: Flame, swatch: "#fbbf24" },
|
||||||
{ value: "rosewood", label: "Rosewood", icon: Wine, swatch: "#fb7185" },
|
{ value: "rosewood", label: "Rosewood", icon: Wine, swatch: "#fb7185" },
|
||||||
{ value: "cyberpunk", label: "Cyberpunk", icon: CircuitBoard, swatch: "#ff2bd6" },
|
{ value: "cyberpunk", label: "Cyberpunk", icon: CircuitBoard, swatch: "#ff2bd6" },
|
||||||
|
{ value: "starfield", label: "Starfield", icon: Orbit, swatch: "#38bdf8" },
|
||||||
];
|
];
|
||||||
const ALL_OPTIONS = [...LIGHT_OPTIONS, ...DARK_OPTIONS];
|
const ALL_OPTIONS = [...LIGHT_OPTIONS, ...DARK_OPTIONS];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue