Organize/app/globals.css

2275 lines
77 KiB
CSS

@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";
@import "@uiw/react-md-editor/markdown-editor.css";
@import "@uiw/react-markdown-preview/markdown.css";
/* "dark:" must be true for every dark-surfaced theme, not just .dark --
the dark looks (Dark, Ocean, Pine, Plum, Midnight, Ember, Rosewood,
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 *, .theme-starfield *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-sans);
--font-mono: var(--font-mono);
--font-heading: var(--font-heading);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar: var(--sidebar);
--color-chart-5: var(--chart-5);
--color-chart-4: var(--chart-4);
--color-chart-3: var(--chart-3);
--color-chart-2: var(--chart-2);
--color-chart-1: var(--chart-1);
--color-ring: var(--ring);
--color-input: var(--input);
--color-border: var(--border);
--color-destructive: var(--destructive);
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-muted-foreground: var(--muted-foreground);
--color-muted: var(--muted);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-popover-foreground: var(--popover-foreground);
--color-popover: var(--popover);
--color-card-foreground: var(--card-foreground);
--color-card: var(--card);
/* One more surface: the "lane" behind a category's cards -- sits between
the page background and the card, so cards read as objects resting on a
tray instead of floating on the page. */
--color-lane: var(--lane);
--radius-sm: calc(var(--radius) * 0.6);
--radius-md: calc(var(--radius) * 0.8);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) * 1.4);
--radius-2xl: calc(var(--radius) * 1.8);
--radius-3xl: calc(var(--radius) * 2.2);
--radius-4xl: calc(var(--radius) * 2.6);
}
/* ---------------------------------------------------------------------------
Themes
The app ships sixteen looks, chosen via the theme picker:
Light:
default -- calm, cool neutral light theme (the safe, focused one)
sunset -- warm paper + persimmon accent, a cozier light theme
meadow -- fresh green paper with an emerald accent
honey -- buttercream paper with a honey-amber accent
rose -- soft pink paper with a raspberry accent ("Ros\xe9")
lavender -- lilac paper with a violet accent
slate -- cool grey-blue paper with a steel-blue accent
blueprint -- EXTRA: deep cobalt drafting-paper background with
white paper cards + cobalt-ink lettering, grid +
registration marks, sharp corners, hand-drawn headings
Dark:
dark -- deep charcoal with an indigo accent
ocean -- deep blue-green night theme with a seafoam accent
pine -- deep forest green with a mint accent
plum -- deep plum night with an orchid accent
midnight -- near-black navy with an ice-periwinkle accent
ember -- warm hearth charcoal with a glowing amber accent
rosewood -- deep wine with a rose accent
cyberpunk -- EXTRA: near-black violet, neon magenta + cyan,
scanlines, glitch, glow, VT323 pixel face
Each is a complete token set; components only ever use tokens, so adding
another theme later is just another block like these. The two EXTRA
themes additionally carry their own fonts, backgrounds, and animations,
all scoped in the "extras" section below.
--------------------------------------------------------------------------- */
:root,
.theme-default {
color-scheme: light;
--background: oklch(0.985 0.002 260);
--foreground: oklch(0.235 0.02 265);
--card: oklch(1 0 0);
--card-foreground: oklch(0.235 0.02 265);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.235 0.02 265);
/* Single calm accent (indigo) for interactive chrome -- buttons, active
nav, focus rings -- kept deliberately separate from the curated vibrant
Group palette in lib/colors.ts so the group colors stay the only
"loud" color on screen. */
--primary: oklch(0.53 0.2 272);
--primary-foreground: oklch(0.98 0.01 274);
--secondary: oklch(0.955 0.004 260);
--secondary-foreground: oklch(0.31 0.02 265);
--muted: oklch(0.95 0.004 260);
--muted-foreground: oklch(0.52 0.02 265);
--accent: oklch(0.95 0.022 272);
--accent-foreground: oklch(0.35 0.12 272);
--destructive: oklch(0.58 0.21 27);
--border: oklch(0.905 0.004 260);
--input: oklch(0.885 0.004 260);
--ring: oklch(0.58 0.15 272);
--lane: oklch(0.95 0.005 260);
--chart-1: oklch(0.87 0 0);
--chart-2: oklch(0.556 0 0);
--chart-3: oklch(0.439 0 0);
--chart-4: oklch(0.371 0 0);
--chart-5: oklch(0.269 0 0);
--radius: 0.75rem;
--sidebar: oklch(0.975 0.003 260);
--sidebar-foreground: oklch(0.235 0.02 265);
--sidebar-primary: oklch(0.53 0.2 272);
--sidebar-primary-foreground: oklch(0.98 0.01 274);
--sidebar-accent: oklch(0.95 0.022 272);
--sidebar-accent-foreground: oklch(0.35 0.12 272);
--sidebar-border: oklch(0.905 0.004 260);
--sidebar-ring: oklch(0.58 0.15 272);
}
.dark {
color-scheme: dark;
--background: oklch(0.175 0.012 265);
--foreground: oklch(0.93 0.01 265);
--card: oklch(0.22 0.013 265);
--card-foreground: oklch(0.93 0.01 265);
--popover: oklch(0.23 0.014 265);
--popover-foreground: oklch(0.93 0.01 265);
--primary: oklch(0.7 0.14 272);
--primary-foreground: oklch(0.16 0.04 272);
--secondary: oklch(0.27 0.012 265);
--secondary-foreground: oklch(0.93 0.01 265);
--muted: oklch(0.26 0.013 265);
--muted-foreground: oklch(0.68 0.02 265);
--accent: oklch(0.31 0.04 272);
--accent-foreground: oklch(0.9 0.03 272);
--destructive: oklch(0.68 0.19 24);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 14%);
--ring: oklch(0.68 0.14 272);
--lane: oklch(1 0 0 / 5%);
--chart-1: oklch(0.87 0 0);
--chart-2: oklch(0.556 0 0);
--chart-3: oklch(0.439 0 0);
--chart-4: oklch(0.371 0 0);
--chart-5: oklch(0.269 0 0);
--radius: 0.75rem;
--sidebar: oklch(0.205 0.013 265);
--sidebar-foreground: oklch(0.93 0.01 265);
--sidebar-primary: oklch(0.7 0.14 272);
--sidebar-primary-foreground: oklch(0.16 0.04 272);
--sidebar-accent: oklch(0.31 0.04 272);
--sidebar-accent-foreground: oklch(0.9 0.03 272);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.68 0.14 272);
}
.theme-sunset {
color-scheme: light;
--background: oklch(0.968 0.016 75);
--foreground: oklch(0.27 0.032 52);
--card: oklch(0.988 0.008 80);
--card-foreground: oklch(0.27 0.032 52);
--popover: oklch(0.99 0.007 80);
--popover-foreground: oklch(0.27 0.032 52);
/* Persimmon -- warm enough to feel like part of the paper, saturated
enough to stay unmistakably "the accent". */
--primary: oklch(0.565 0.19 42);
--primary-foreground: oklch(0.98 0.01 60);
--secondary: oklch(0.945 0.02 72);
--secondary-foreground: oklch(0.32 0.05 50);
--muted: oklch(0.938 0.02 72);
--muted-foreground: oklch(0.52 0.045 58);
--accent: oklch(0.928 0.035 62);
--accent-foreground: oklch(0.36 0.11 44);
--destructive: oklch(0.57 0.21 25);
--border: oklch(0.89 0.022 72);
--input: oklch(0.865 0.024 72);
--ring: oklch(0.6 0.16 44);
--lane: oklch(0.942 0.018 72);
--chart-1: oklch(0.79 0.12 58);
--chart-2: oklch(0.66 0.14 48);
--chart-3: oklch(0.53 0.13 42);
--chart-4: oklch(0.42 0.1 52);
--chart-5: oklch(0.31 0.07 58);
/* Slightly rounder than the default theme -- a touch softer overall. */
--radius: 0.9rem;
--sidebar: oklch(0.958 0.013 75);
--sidebar-foreground: oklch(0.27 0.032 52);
--sidebar-primary: oklch(0.565 0.19 42);
--sidebar-primary-foreground: oklch(0.98 0.01 60);
--sidebar-accent: oklch(0.928 0.035 62);
--sidebar-accent-foreground: oklch(0.36 0.11 44);
--sidebar-border: oklch(0.89 0.022 72);
--sidebar-ring: oklch(0.6 0.16 44);
}
.ocean {
color-scheme: dark;
--background: oklch(0.2 0.035 224);
--foreground: oklch(0.92 0.02 215);
--card: oklch(0.245 0.04 220);
--card-foreground: oklch(0.92 0.02 215);
--popover: oklch(0.255 0.042 218);
--popover-foreground: oklch(0.92 0.02 215);
/* Seafoam -- a cool, luminous accent that reads "water at night" against
the deep blue-green surfaces without screaming. */
--primary: oklch(0.76 0.11 192);
--primary-foreground: oklch(0.21 0.05 200);
--secondary: oklch(0.295 0.042 222);
--secondary-foreground: oklch(0.92 0.02 215);
--muted: oklch(0.285 0.042 222);
--muted-foreground: oklch(0.7 0.03 215);
--accent: oklch(0.33 0.05 214);
--accent-foreground: oklch(0.9 0.03 192);
--destructive: oklch(0.7 0.17 25);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 14%);
--ring: oklch(0.72 0.11 192);
--lane: oklch(1 0 0 / 6%);
--chart-1: oklch(0.76 0.1 192);
--chart-2: oklch(0.63 0.11 200);
--chart-3: oklch(0.5 0.11 215);
--chart-4: oklch(0.4 0.1 228);
--chart-5: oklch(0.3 0.08 240);
--radius: 0.8rem;
--sidebar: oklch(0.225 0.042 220);
--sidebar-foreground: oklch(0.92 0.02 215);
--sidebar-primary: oklch(0.76 0.11 192);
--sidebar-primary-foreground: oklch(0.21 0.05 200);
--sidebar-accent: oklch(0.33 0.05 214);
--sidebar-accent-foreground: oklch(0.9 0.03 192);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.72 0.11 192);
}
/* Meadow -- fresh green paper + emerald accent: a spring morning on the desk.
Light-surfaced; pairs with the neutral group palette as well as anything.
*/
.theme-meadow {
color-scheme: light;
--background: oklch(0.975 0.012 145);
--foreground: oklch(0.26 0.03 150);
--card: oklch(0.99 0.006 145);
--card-foreground: oklch(0.26 0.03 150);
--popover: oklch(0.992 0.005 145);
--popover-foreground: oklch(0.26 0.03 150);
/* Emerald -- leafy enough to feel grown, saturated enough to lead. */
--primary: oklch(0.52 0.16 155);
--primary-foreground: oklch(0.98 0.01 145);
--secondary: oklch(0.945 0.018 145);
--secondary-foreground: oklch(0.31 0.05 150);
--muted: oklch(0.938 0.016 145);
--muted-foreground: oklch(0.515 0.04 150);
--accent: oklch(0.925 0.03 150);
--accent-foreground: oklch(0.35 0.1 155);
--destructive: oklch(0.57 0.21 25);
--border: oklch(0.89 0.018 145);
--input: oklch(0.86 0.02 145);
--ring: oklch(0.57 0.14 155);
--lane: oklch(0.94 0.015 145);
--chart-1: oklch(0.8 0.08 145);
--chart-2: oklch(0.68 0.11 152);
--chart-3: oklch(0.55 0.12 158);
--chart-4: oklch(0.44 0.1 152);
--chart-5: oklch(0.33 0.08 148);
--radius: 0.8rem;
--sidebar: oklch(0.965 0.01 145);
--sidebar-foreground: oklch(0.26 0.03 150);
--sidebar-primary: oklch(0.52 0.16 155);
--sidebar-primary-foreground: oklch(0.98 0.01 145);
--sidebar-accent: oklch(0.925 0.03 150);
--sidebar-accent-foreground: oklch(0.35 0.1 155);
--sidebar-border: oklch(0.89 0.018 145);
--sidebar-ring: oklch(0.57 0.14 155);
}
/* Honey -- buttercream paper + honey-amber accent: golden hour, mellowed.
Light-surfaced; warmer than Sunset's terracotta, softer and yellower. */
.theme-honey {
color-scheme: light;
--background: oklch(0.972 0.024 95);
--foreground: oklch(0.28 0.04 80);
--card: oklch(0.988 0.015 95);
--card-foreground: oklch(0.28 0.04 80);
--popover: oklch(0.99 0.014 95);
--popover-foreground: oklch(0.28 0.04 80);
/* Honey-amber -- glowing but gentle, like light through glass. */
--primary: oklch(0.555 0.16 70);
--primary-foreground: oklch(0.98 0.015 90);
--secondary: oklch(0.948 0.03 92);
--secondary-foreground: oklch(0.33 0.06 78);
--muted: oklch(0.94 0.028 92);
--muted-foreground: oklch(0.52 0.05 82);
--accent: oklch(0.93 0.04 88);
--accent-foreground: oklch(0.37 0.11 75);
--destructive: oklch(0.57 0.21 25);
--border: oklch(0.885 0.03 90);
--input: oklch(0.855 0.032 90);
--ring: oklch(0.62 0.14 78);
--lane: oklch(0.942 0.026 92);
--chart-1: oklch(0.82 0.1 85);
--chart-2: oklch(0.7 0.13 78);
--chart-3: oklch(0.58 0.14 72);
--chart-4: oklch(0.47 0.12 75);
--chart-5: oklch(0.36 0.09 80);
/* A touch softer than default -- honey is meant to feel mellow. */
--radius: 0.85rem;
--sidebar: oklch(0.962 0.02 95);
--sidebar-foreground: oklch(0.28 0.04 80);
--sidebar-primary: oklch(0.555 0.16 70);
--sidebar-primary-foreground: oklch(0.98 0.015 90);
--sidebar-accent: oklch(0.93 0.04 88);
--sidebar-accent-foreground: oklch(0.37 0.11 75);
--sidebar-border: oklch(0.885 0.03 90);
--sidebar-ring: oklch(0.62 0.14 78);
}
/* Ros\xe9 -- soft pink paper + raspberry accent: a blush, not a ballroom.
Light-surfaced. */
.theme-rose {
color-scheme: light;
--background: oklch(0.972 0.014 15);
--foreground: oklch(0.27 0.035 15);
--card: oklch(0.988 0.008 18);
--card-foreground: oklch(0.27 0.035 15);
--popover: oklch(0.99 0.008 18);
--popover-foreground: oklch(0.27 0.035 15);
/* Raspberry -- enough punch to be the accent, sweet enough to sit
comfortably inside the pink paper. */
--primary: oklch(0.55 0.19 12);
--primary-foreground: oklch(0.98 0.01 20);
--secondary: oklch(0.948 0.02 15);
--secondary-foreground: oklch(0.32 0.06 12);
--muted: oklch(0.94 0.018 15);
--muted-foreground: oklch(0.525 0.045 12);
--accent: oklch(0.93 0.032 14);
--accent-foreground: oklch(0.36 0.11 12);
/* A deeper red than the rest of the pink, so errors still read as errors. */
--destructive: oklch(0.55 0.22 20);
--border: oklch(0.888 0.022 15);
--input: oklch(0.86 0.024 15);
--ring: oklch(0.58 0.16 14);
--lane: oklch(0.942 0.02 15);
--chart-1: oklch(0.8 0.07 20);
--chart-2: oklch(0.68 0.11 15);
--chart-3: oklch(0.56 0.13 12);
--chart-4: oklch(0.45 0.12 10);
--chart-5: oklch(0.34 0.09 15);
/* Softer corners -- the most romantic look in the set. */
--radius: 0.9rem;
--sidebar: oklch(0.962 0.012 15);
--sidebar-foreground: oklch(0.27 0.035 15);
--sidebar-primary: oklch(0.55 0.19 12);
--sidebar-primary-foreground: oklch(0.98 0.01 20);
--sidebar-accent: oklch(0.93 0.032 14);
--sidebar-accent-foreground: oklch(0.36 0.11 12);
--sidebar-border: oklch(0.888 0.022 15);
--sidebar-ring: oklch(0.58 0.16 14);
}
/* Lavender -- lilac paper + violet accent: dusk without the dark.
Light-surfaced. */
.theme-lavender {
color-scheme: light;
--background: oklch(0.972 0.012 300);
--foreground: oklch(0.27 0.035 305);
--card: oklch(0.988 0.008 300);
--card-foreground: oklch(0.27 0.035 305);
--popover: oklch(0.99 0.008 300);
--popover-foreground: oklch(0.27 0.035 305);
/* Violet -- a little more saturated than the paper's tint so it leads. */
--primary: oklch(0.53 0.19 300);
--primary-foreground: oklch(0.98 0.01 300);
--secondary: oklch(0.948 0.018 300);
--secondary-foreground: oklch(0.32 0.06 305);
--muted: oklch(0.94 0.016 300);
--muted-foreground: oklch(0.525 0.045 305);
--accent: oklch(0.93 0.03 302);
--accent-foreground: oklch(0.36 0.11 305);
--destructive: oklch(0.57 0.21 25);
--border: oklch(0.888 0.018 300);
--input: oklch(0.86 0.02 300);
--ring: oklch(0.56 0.16 300);
--lane: oklch(0.942 0.015 300);
--chart-1: oklch(0.8 0.07 300);
--chart-2: oklch(0.68 0.11 302);
--chart-3: oklch(0.56 0.13 305);
--chart-4: oklch(0.45 0.12 308);
--chart-5: oklch(0.34 0.09 305);
--radius: 0.85rem;
--sidebar: oklch(0.962 0.012 300);
--sidebar-foreground: oklch(0.27 0.035 305);
--sidebar-primary: oklch(0.53 0.19 300);
--sidebar-primary-foreground: oklch(0.98 0.01 300);
--sidebar-accent: oklch(0.93 0.03 302);
--sidebar-accent-foreground: oklch(0.36 0.11 305);
--sidebar-border: oklch(0.888 0.018 300);
--sidebar-ring: oklch(0.56 0.16 300);
}
/* Slate -- cool grey-blue paper + steel-blue accent: the "work mode" look.
Light-surfaced; the crispest corners in the set. */
.theme-slate {
color-scheme: light;
--background: oklch(0.968 0.006 240);
--foreground: oklch(0.25 0.02 245);
--card: oklch(0.985 0.004 240);
--card-foreground: oklch(0.25 0.02 245);
--popover: oklch(0.988 0.004 240);
--popover-foreground: oklch(0.25 0.02 245);
/* Steel blue -- calmer than Default's indigo, quieter by design. */
--primary: oklch(0.52 0.11 240);
--primary-foreground: oklch(0.98 0.005 240);
--secondary: oklch(0.945 0.008 240);
--secondary-foreground: oklch(0.31 0.03 245);
--muted: oklch(0.938 0.008 240);
--muted-foreground: oklch(0.52 0.02 245);
--accent: oklch(0.925 0.014 242);
--accent-foreground: oklch(0.35 0.08 245);
--destructive: oklch(0.57 0.2 25);
--border: oklch(0.895 0.006 240);
--input: oklch(0.875 0.006 240);
--ring: oklch(0.55 0.09 240);
--lane: oklch(0.94 0.007 240);
--chart-1: oklch(0.82 0.04 240);
--chart-2: oklch(0.7 0.06 242);
--chart-3: oklch(0.58 0.08 244);
--chart-4: oklch(0.47 0.07 246);
--chart-5: oklch(0.36 0.05 248);
/* Crisper corners -- the most "engineered" look in the set. */
--radius: 0.7rem;
--sidebar: oklch(0.958 0.005 240);
--sidebar-foreground: oklch(0.25 0.02 245);
--sidebar-primary: oklch(0.52 0.11 240);
--sidebar-primary-foreground: oklch(0.98 0.005 240);
--sidebar-accent: oklch(0.925 0.014 242);
--sidebar-accent-foreground: oklch(0.35 0.08 245);
--sidebar-border: oklch(0.895 0.006 240);
--sidebar-ring: oklch(0.55 0.09 240);
}
/* Pine -- deep forest green night + mint accent: the woods after rain.
Dark-surfaced (see the `dark` custom-variant above). */
.theme-pine {
color-scheme: dark;
--background: oklch(0.2 0.035 160);
--foreground: oklch(0.92 0.02 150);
--card: oklch(0.245 0.04 158);
--card-foreground: oklch(0.92 0.02 150);
--popover: oklch(0.255 0.042 156);
--popover-foreground: oklch(0.92 0.02 150);
/* Mint -- luminous against the deep green, without Ocean's cool cast. */
--primary: oklch(0.76 0.12 165);
--primary-foreground: oklch(0.2 0.05 160);
--secondary: oklch(0.295 0.042 158);
--secondary-foreground: oklch(0.92 0.02 150);
--muted: oklch(0.285 0.04 158);
--muted-foreground: oklch(0.7 0.03 150);
--accent: oklch(0.33 0.05 160);
--accent-foreground: oklch(0.9 0.03 165);
--destructive: oklch(0.7 0.17 25);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 14%);
--ring: oklch(0.72 0.1 165);
--lane: oklch(1 0 0 / 6%);
--chart-1: oklch(0.76 0.1 165);
--chart-2: oklch(0.63 0.11 160);
--chart-3: oklch(0.5 0.11 155);
--chart-4: oklch(0.4 0.09 150);
--chart-5: oklch(0.3 0.07 150);
--radius: 0.8rem;
--sidebar: oklch(0.225 0.04 158);
--sidebar-foreground: oklch(0.92 0.02 150);
--sidebar-primary: oklch(0.76 0.12 165);
--sidebar-primary-foreground: oklch(0.2 0.05 160);
--sidebar-accent: oklch(0.33 0.05 160);
--sidebar-accent-foreground: oklch(0.9 0.03 165);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.72 0.1 165);
}
/* Plum -- deep plum night + orchid accent: the richest dark in the set.
Dark-surfaced. */
.theme-plum {
color-scheme: dark;
--background: oklch(0.2 0.03 315);
--foreground: oklch(0.92 0.02 320);
--card: oklch(0.245 0.035 315);
--card-foreground: oklch(0.92 0.02 320);
--popover: oklch(0.255 0.038 315);
--popover-foreground: oklch(0.92 0.02 320);
/* Orchid -- bright enough to lead the eye, deep enough to stay nocturnal. */
--primary: oklch(0.74 0.13 320);
--primary-foreground: oklch(0.2 0.05 315);
--secondary: oklch(0.295 0.04 315);
--secondary-foreground: oklch(0.92 0.02 320);
--muted: oklch(0.285 0.04 315);
--muted-foreground: oklch(0.7 0.03 320);
--accent: oklch(0.33 0.05 318);
--accent-foreground: oklch(0.9 0.03 322);
--destructive: oklch(0.7 0.17 25);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 14%);
--ring: oklch(0.7 0.12 320);
--lane: oklch(1 0 0 / 6%);
--chart-1: oklch(0.76 0.1 320);
--chart-2: oklch(0.63 0.11 318);
--chart-3: oklch(0.5 0.11 315);
--chart-4: oklch(0.4 0.1 312);
--chart-5: oklch(0.3 0.08 315);
--radius: 0.8rem;
--sidebar: oklch(0.225 0.035 315);
--sidebar-foreground: oklch(0.92 0.02 320);
--sidebar-primary: oklch(0.74 0.13 320);
--sidebar-primary-foreground: oklch(0.2 0.05 315);
--sidebar-accent: oklch(0.33 0.05 318);
--sidebar-accent-foreground: oklch(0.9 0.03 322);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.7 0.12 320);
}
/* Midnight -- the darkest surface in the set, near-black navy, with an
ice-periwinkle accent: a clear winter night.
Dark-surfaced. */
.theme-midnight {
color-scheme: dark;
--background: oklch(0.16 0.02 262);
--foreground: oklch(0.93 0.01 258);
--card: oklch(0.2 0.022 260);
--card-foreground: oklch(0.93 0.01 258);
--popover: oklch(0.21 0.024 260);
--popover-foreground: oklch(0.93 0.01 258);
/* Ice periwinkle -- pale and cool, a thin light against the black. */
--primary: oklch(0.76 0.09 255);
--primary-foreground: oklch(0.17 0.03 260);
--secondary: oklch(0.255 0.024 262);
--secondary-foreground: oklch(0.93 0.01 258);
--muted: oklch(0.245 0.024 262);
--muted-foreground: oklch(0.7 0.015 258);
--accent: oklch(0.29 0.035 260);
--accent-foreground: oklch(0.9 0.02 255);
--destructive: oklch(0.7 0.17 25);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 14%);
--ring: oklch(0.74 0.08 255);
--lane: oklch(1 0 0 / 6%);
--chart-1: oklch(0.78 0.07 255);
--chart-2: oklch(0.66 0.08 258);
--chart-3: oklch(0.54 0.09 260);
--chart-4: oklch(0.44 0.08 262);
--chart-5: oklch(0.34 0.06 265);
--radius: 0.75rem;
--sidebar: oklch(0.185 0.022 262);
--sidebar-foreground: oklch(0.93 0.01 258);
--sidebar-primary: oklch(0.76 0.09 255);
--sidebar-primary-foreground: oklch(0.17 0.03 260);
--sidebar-accent: oklch(0.29 0.035 260);
--sidebar-accent-foreground: oklch(0.9 0.02 255);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.74 0.08 255);
}
/* Ember -- warm hearth charcoal + glowing amber accent: Sunset's dark twin.
Dark-surfaced. */
.theme-ember {
color-scheme: dark;
--background: oklch(0.2 0.025 45);
--foreground: oklch(0.92 0.015 60);
--card: oklch(0.245 0.028 48);
--card-foreground: oklch(0.92 0.015 60);
--popover: oklch(0.255 0.03 48);
--popover-foreground: oklch(0.92 0.015 60);
/* Ember amber -- warm glow, like coals catching the evening. */
--primary: oklch(0.72 0.14 62);
--primary-foreground: oklch(0.2 0.04 50);
--secondary: oklch(0.295 0.03 50);
--secondary-foreground: oklch(0.92 0.015 60);
--muted: oklch(0.285 0.03 50);
--muted-foreground: oklch(0.7 0.025 55);
--accent: oklch(0.33 0.04 52);
--accent-foreground: oklch(0.9 0.03 62);
--destructive: oklch(0.7 0.17 25);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 14%);
--ring: oklch(0.7 0.12 62);
--lane: oklch(1 0 0 / 6%);
--chart-1: oklch(0.78 0.1 58);
--chart-2: oklch(0.66 0.12 55);
--chart-3: oklch(0.54 0.12 52);
--chart-4: oklch(0.44 0.1 50);
--chart-5: oklch(0.34 0.08 52);
--radius: 0.85rem;
--sidebar: oklch(0.225 0.028 48);
--sidebar-foreground: oklch(0.92 0.015 60);
--sidebar-primary: oklch(0.72 0.14 62);
--sidebar-primary-foreground: oklch(0.2 0.04 50);
--sidebar-accent: oklch(0.33 0.04 52);
--sidebar-accent-foreground: oklch(0.9 0.03 62);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.7 0.12 62);
}
/* Rosewood -- deep wine + rose accent: Ros\xe9's dark twin.
Dark-surfaced. */
.theme-rosewood {
color-scheme: dark;
--background: oklch(0.2 0.04 18);
--foreground: oklch(0.92 0.02 20);
--card: oklch(0.245 0.045 18);
--card-foreground: oklch(0.92 0.02 20);
--popover: oklch(0.255 0.048 18);
--popover-foreground: oklch(0.92 0.02 20);
/* Rose -- bright enough to lead, warm enough to stay in the wine. */
--primary: oklch(0.74 0.13 20);
--primary-foreground: oklch(0.2 0.05 15);
--secondary: oklch(0.295 0.045 18);
--secondary-foreground: oklch(0.92 0.02 20);
--muted: oklch(0.285 0.045 18);
--muted-foreground: oklch(0.7 0.03 20);
--accent: oklch(0.33 0.055 18);
--accent-foreground: oklch(0.9 0.03 22);
--destructive: oklch(0.7 0.17 25);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 14%);
--ring: oklch(0.72 0.11 20);
--lane: oklch(1 0 0 / 6%);
--chart-1: oklch(0.78 0.09 20);
--chart-2: oklch(0.66 0.11 18);
--chart-3: oklch(0.54 0.12 16);
--chart-4: oklch(0.44 0.1 15);
--chart-5: oklch(0.34 0.08 18);
--radius: 0.85rem;
--sidebar: oklch(0.225 0.045 18);
--sidebar-foreground: oklch(0.92 0.02 20);
--sidebar-primary: oklch(0.74 0.13 20);
--sidebar-primary-foreground: oklch(0.2 0.05 15);
--sidebar-accent: oklch(0.33 0.055 18);
--sidebar-accent-foreground: oklch(0.9 0.03 22);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.72 0.11 20);
}
/* Blueprint -- a deep cobalt drafting board with white drafting paper on
top: the sheet is the white card, the ink is cobalt blue. It's a *light*
surface (the working paper is white with dark blue ink), but the page
backdrop stays deep cobalt like a blueprint under glass. The board chrome
(titles, lane labels, buttons) that sits directly on the cobalt uses the
near-white `--foreground`; the paper carries the cobalt `--card-foreground`
ink (see the extras section, which also re-inks the group-card title and
the board chrome's muted text). Sharp corners, a bright azure highlighter
for focus, and a hand-drawn architectural face. */
.theme-blueprint {
color-scheme: light;
/* The board: deep drafting cobalt. */
--background: oklch(0.42 0.13 255);
/* Board chrome ink -- sits on the cobalt, so it's near-white. */
--foreground: oklch(0.97 0.01 225);
/* The paper: warm near-white drafting sheet. */
--card: oklch(0.976 0.006 250);
/* Drafting ink: the cobalt pen that writes on the paper. */
--card-foreground: oklch(0.43 0.13 255);
--popover: oklch(0.976 0.006 250);
--popover-foreground: oklch(0.43 0.13 255);
/* The action color: a strong cobalt pen stroke. */
--primary: oklch(0.47 0.16 255);
--primary-foreground: oklch(0.99 0 0);
--secondary: oklch(0.915 0.03 250);
--secondary-foreground: oklch(0.4 0.13 255);
--muted: oklch(0.93 0.022 250);
/* Drafting ink at a muted weight (secondary text on the paper). */
--muted-foreground: oklch(0.47 0.12 255);
--accent: oklch(0.895 0.045 250);
--accent-foreground: oklch(0.38 0.13 255);
--destructive: oklch(0.58 0.2 25);
--destructive-foreground: oklch(0.99 0 0);
--border: oklch(0.74 0.06 250);
--input: oklch(0.74 0.06 250);
/* Bright azure highlighter for focus + registration marks. */
--ring: oklch(0.72 0.16 215);
--lane: oklch(1 0 0 / 8%);
--chart-1: oklch(0.58 0.14 250);
--chart-2: oklch(0.66 0.14 200);
--chart-3: oklch(0.6 0.13 180);
--chart-4: oklch(0.58 0.13 120);
--chart-5: oklch(0.6 0.14 60);
/* Sharp, technical corners. */
--radius: 0.15rem;
--sidebar: oklch(0.45 0.125 255);
--sidebar-foreground: oklch(0.96 0.01 225);
--sidebar-primary: oklch(0.97 0.01 225);
--sidebar-primary-foreground: oklch(0.4 0.13 255);
--sidebar-accent: oklch(0.5 0.11 255);
--sidebar-accent-foreground: oklch(0.97 0.01 225);
--sidebar-border: oklch(1 0 0 / 30%);
--sidebar-ring: oklch(0.72 0.16 215);
}
/* Cyberpunk -- near-black violet night + neon magenta with an electric-cyan
secondary: the loud one. Dark-surfaced; see the extras section for the
scanlines, glitch, glow, and VT323 pixel face. */
.theme-cyberpunk {
color-scheme: dark;
--background: oklch(0.16 0.03 290);
--foreground: oklch(0.9 0.03 210);
--card: oklch(0.2 0.035 290);
--card-foreground: oklch(0.9 0.03 210);
--popover: oklch(0.21 0.04 290);
--popover-foreground: oklch(0.9 0.03 210);
/* Neon magenta -- the city at night, at full saturation. */
--primary: oklch(0.72 0.24 350);
--primary-foreground: oklch(0.16 0.03 300);
--secondary: oklch(0.24 0.045 290);
--secondary-foreground: oklch(0.88 0.06 200);
--muted: oklch(0.23 0.04 290);
--muted-foreground: oklch(0.7 0.03 220);
--accent: oklch(0.28 0.06 295);
--accent-foreground: oklch(0.92 0.06 350);
--destructive: oklch(0.68 0.23 30);
--border: oklch(0.9 0.06 210 / 22%);
--input: oklch(0.9 0.06 210 / 16%);
/* Electric-cyan focus. */
--ring: oklch(0.85 0.14 195);
--lane: oklch(1 0 0 / 6%);
--chart-1: oklch(0.85 0.15 195);
--chart-2: oklch(0.75 0.18 280);
--chart-3: oklch(0.68 0.22 350);
--chart-4: oklch(0.78 0.14 230);
--chart-5: oklch(0.9 0.03 200);
/* Angular chrome. */
--radius: 0.2rem;
--sidebar: oklch(0.185 0.035 290);
--sidebar-foreground: oklch(0.9 0.03 210);
--sidebar-primary: oklch(0.72 0.24 350);
--sidebar-primary-foreground: oklch(0.16 0.03 300);
--sidebar-accent: oklch(0.28 0.06 295);
--sidebar-accent-foreground: oklch(0.92 0.06 350);
--sidebar-border: oklch(0.9 0.06 210 / 22%);
--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, Cyberpunk, Vaporwave, Starfield,
and Notebook each carry their own fonts, backgrounds, and animations.
Everything here is scoped under the theme's own class on <html>, so no
other theme is touched. The reduced-motion guard in @layer base still
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 -------------------------------- */
/* Engineering grid on the drafting paper: fine 16px squares with a bolder
96px major line, fixed to the viewport like a drawing under glass. */
html.theme-blueprint body {
background-image:
linear-gradient(rgb(255 255 255 / 0.14) 1px, transparent 1px),
linear-gradient(90deg, rgb(255 255 255 / 0.14) 1px, transparent 1px),
linear-gradient(rgb(255 255 255 / 0.06) 1px, transparent 1px),
linear-gradient(90deg, rgb(255 255 255 / 0.06) 1px, transparent 1px);
background-size:
96px 96px,
96px 96px,
16px 16px,
16px 16px;
background-attachment: fixed;
}
/* The drafting face carries the whole sheet: a hand-drawn architectural face
(Architects Daughter) for headings AND for the body/to-do text -- everything
reads as lettered by hand, not just the title blocks. We retarget the
theme's sans variable so every `font-sans` surface (to-dos, buttons, nav,
note editor) picks it up. */
html.theme-blueprint {
--font-sans: var(--font-blueprint), "Segoe Print", "Bradley Hand", cursive;
--font-heading: var(--font-blueprint), "Segoe Print", "Bradley Hand", cursive;
}
/* The base body sets a tight negative letter-spacing tuned for Inter -- a
handwriting face crowds under it, so relax it back to natural spacing. */
html.theme-blueprint body,
html.theme-blueprint h1,
html.theme-blueprint h2,
html.theme-blueprint h3,
html.theme-blueprint h4 {
letter-spacing: 0;
}
/* Headings: keep the natural hand-drawn weight -- faux-bolding a single-weight
handwriting face blurs its strokes, so hold the title blocks at 400. */
html.theme-blueprint .font-heading {
font-weight: 400;
}
/* Sharp, technical corners across the UI (rounded-full stays round --
progress rings, check marks, dots keep their circles). */
html.theme-blueprint .rounded-2xl {
border-radius: 4px;
}
html.theme-blueprint .rounded-xl {
border-radius: 3px;
}
html.theme-blueprint .rounded-lg {
border-radius: 2px;
}
/* Group cards: dashed stroke, like a layer outline on a drawing, plus a deep
cobalt offset shadow for a sheet-of-paper lift off the board. */
html.theme-blueprint .border-\[3px\] {
border-style: dashed;
box-shadow: 5px 5px 0 0 rgb(14 24 64 / 0.32);
}
/* Standard cards and dialogs get a double drafting frame: a thin cobalt inner
line plus a deep offset, like a mounted sheet. */
html.theme-blueprint [data-slot="card"],
html.theme-blueprint [data-slot="dialog-content"] {
box-shadow:
0 0 0 1px rgb(40 60 160 / 0.28),
5px 5px 0 0 rgb(14 24 64 / 0.3);
}
/* You're at a drafting table -- crosshair everywhere (inputs keep the
text cursor via UA defaults). */
html.theme-blueprint {
cursor: crosshair;
}
/* Registration marks: corner brackets snap onto buttons on hover/focus,
like aligning a plotter. */
html.theme-blueprint [data-slot="button"] {
position: relative;
}
html.theme-blueprint [data-slot="button"]::before,
html.theme-blueprint [data-slot="button"]::after {
content: "";
position: absolute;
width: 10px;
height: 10px;
border: 1px solid var(--ring);
opacity: 0;
pointer-events: none;
transition:
opacity 150ms ease,
transform 150ms ease;
}
html.theme-blueprint [data-slot="button"]::before {
top: -4px;
left: -4px;
border-right: 0;
border-bottom: 0;
transform: translate(3px, 3px);
}
html.theme-blueprint [data-slot="button"]::after {
bottom: -4px;
right: -4px;
border-left: 0;
border-top: 0;
transform: translate(-3px, -3px);
}
html.theme-blueprint [data-slot="button"]:hover::before,
html.theme-blueprint [data-slot="button"]:hover::after,
html.theme-blueprint [data-slot="button"]:focus-visible::before,
html.theme-blueprint [data-slot="button"]:focus-visible::after {
opacity: 1;
transform: translate(0, 0);
}
/* Completed to-dos: a slightly heavier, pen-weight strikethrough across the
words. Native line-through spans only the glyphs (not the whole flex row),
so it reads as pen crossing out the text rather than a line across the card. */
html.theme-blueprint .line-through {
text-decoration: line-through;
text-decoration-thickness: 1.5px;
}
/* Then a red-ink "APPROVED" stamp thuds onto the row a beat after the strike
-- a hard scale-down with a small overshoot, settling tilted a few degrees
like a QC stamp pressed onto the drawing. Scoped to the board's to-do rows:
the title button is a flex row, so the stamp rides at its right end (the
scheduled panel's completed rows are truncate buttons, where a flex item
would get clipped by the ellipsis). */
html.theme-blueprint [data-group-card] .line-through::after {
content: "APPROVED";
flex: none;
margin-left: 4px;
padding: 1px 6px;
border: 1.5px solid oklch(0.58 0.2 25 / 0.75);
box-shadow: inset 0 0 0 1px oklch(0.58 0.2 25 / 0.28);
border-radius: 2px;
color: oklch(0.58 0.2 25 / 0.9);
font-size: 10px;
line-height: 1.6;
letter-spacing: 0.08em;
opacity: 0.9;
transform: rotate(-6deg);
animation: bp-stamp 380ms cubic-bezier(0.3, 0.9, 0.4, 1) 160ms backwards;
mix-blend-mode: multiply;
pointer-events: none;
}
@keyframes bp-stamp {
0% {
opacity: 0;
transform: rotate(-14deg) scale(2.1);
}
60% {
opacity: 0.9;
transform: rotate(-5deg) scale(0.92);
}
80% {
transform: rotate(-6.5deg) scale(1.06);
}
100% {
opacity: 0.9;
transform: rotate(-6deg) scale(1);
}
}
/* To-do checkbox: a small technical box -- squarer corner, crisp stroke, and
registration ticks that snap in on hover/focus like a plotter aligning to a
point. (The box is the base-ui checkbox button; its stroke/fill already come
from the group's own accent color.) */
html.theme-blueprint [data-todo-checkbox] {
border-radius: 2px;
}
html.theme-blueprint [data-todo-checkbox]:hover {
box-shadow: 0 0 0 3px rgb(40 60 160 / 0.18);
}
html.theme-blueprint [data-todo-checkbox]::before,
html.theme-blueprint [data-todo-checkbox]::after {
content: "";
position: absolute;
width: 6px;
height: 6px;
border: 1px solid var(--ring);
opacity: 0;
pointer-events: none;
transition: opacity 150ms ease;
}
html.theme-blueprint [data-todo-checkbox]::before {
top: -5px;
left: -5px;
border-right: 0;
border-bottom: 0;
}
html.theme-blueprint [data-todo-checkbox]::after {
bottom: -5px;
right: -5px;
border-left: 0;
border-top: 0;
}
html.theme-blueprint [data-todo-checkbox]:hover::before,
html.theme-blueprint [data-todo-checkbox]:hover::after,
html.theme-blueprint [data-todo-checkbox]:focus-visible::before,
html.theme-blueprint [data-todo-checkbox]:focus-visible::after {
opacity: 1;
}
/* The group card's title inherits the board's near-white foreground, which
would wash out on the white paper -- re-ink the whole card with the cobalt
drafting ink (the open to-do rows already carry their own accent color, and
the muted bits below read correctly on the paper). */
html.theme-blueprint [data-group-card] {
color: var(--card-foreground);
}
/* Board chrome that sits on the cobalt (the lane label, the open-to-do counts,
the add-lane button, the empty state, and the two sidebar columns) uses the
muted ink -- re-ink it light so it reads against the deep board, not the
paper. (Group cards and dialogs/popovers are the white paper and keep the
cobalt ink.) */
html.theme-blueprint [data-board-chrome] .text-muted-foreground,
html.theme-blueprint [data-board-chrome].text-muted-foreground,
html.theme-blueprint .bg-sidebar .text-muted-foreground,
html.theme-blueprint .bg-sidebar.text-muted-foreground {
color: var(--sidebar-foreground);
}
/* ------------------------------ Cyberpunk -------------------------------- */
/* The pixel face runs the whole deck: VT323 for headings AND for the
body/to-do text, so everything reads like a CRT terminal, not just the
headers. We retarget the theme's sans variable so every `font-sans`
surface (to-dos, buttons, nav, note editor) picks it up. */
html.theme-cyberpunk {
--font-sans: var(--font-cyberpunk), ui-monospace, monospace;
--font-heading: var(--font-cyberpunk), ui-monospace, monospace;
}
/* Headings keep the pixel face + a touch of tracking for the terminal feel. */
html.theme-cyberpunk .font-heading {
font-family: var(--font-cyberpunk), monospace;
letter-spacing: 0.04em;
}
/* Angular chrome (rounded-full stays round). */
html.theme-cyberpunk .rounded-2xl {
border-radius: 4px;
}
html.theme-cyberpunk .rounded-xl {
border-radius: 3px;
}
html.theme-cyberpunk .rounded-lg {
border-radius: 2px;
}
/* Faint tron grid under everything. */
html.theme-cyberpunk body {
background-image:
linear-gradient(rgb(34 255 238 / 0.04) 1px, transparent 1px),
linear-gradient(90deg, rgb(34 255 238 / 0.04) 1px, transparent 1px);
background-size: 28px 28px;
}
/* CRT scanlines + vignette over the whole app -- fixed and click-through,
so it sits over dialogs and toasts too, the way a monitor sits over
everything. */
html.theme-cyberpunk body::before {
content: "";
position: fixed;
inset: 0;
z-index: 999;
pointer-events: none;
background:
radial-gradient(120% 90% at 50% 45%, transparent 55%, rgb(0 0 0 / 0.35) 100%),
repeating-linear-gradient(
0deg,
rgb(0 0 0 / 0.12) 0px,
rgb(0 0 0 / 0.12) 1px,
transparent 1px,
transparent 3px
);
}
/* A slow scan band drifting down the screen, like a CRT refresh. */
html.theme-cyberpunk body::after {
content: "";
position: fixed;
left: 0;
right: 0;
top: 0;
height: 15%;
z-index: 999;
pointer-events: none;
background: linear-gradient(
180deg,
transparent,
rgb(34 255 238 / 0.05) 45%,
rgb(255 43 214 / 0.04) 55%,
transparent
);
animation: cp-scan 9s linear infinite;
}
@keyframes cp-scan {
from {
transform: translateY(-120%);
}
to {
transform: translateY(720%);
}
}
/* Neon focus glow on top of the standard ring. */
html.theme-cyberpunk :focus-visible {
box-shadow:
0 0 0 3px color-mix(in oklch, var(--ring) 45%, transparent),
0 0 16px rgb(34 255 238 / 0.4);
}
/* Energized surfaces: anything filled with the primary color blooms. */
html.theme-cyberpunk .bg-primary {
box-shadow: 0 0 14px rgb(255 43 214 / 0.3);
}
/* Glitch: a brief boot flicker whenever the theme (re)applies, and an
RGB-split jitter when a heading is hovered. */
html.theme-cyberpunk .font-heading {
animation: cp-boot 700ms steps(12, jump-none) 1;
}
@keyframes cp-boot {
0% {
opacity: 0;
}
8% {
opacity: 1;
}
14% {
opacity: 0.3;
}
22% {
opacity: 1;
}
30% {
opacity: 0.55;
}
42%,
100% {
opacity: 1;
}
}
html.theme-cyberpunk .font-heading:hover {
text-shadow:
2px 0 rgb(255 43 214 / 0.85),
-2px 0 rgb(34 255 238 / 0.85);
animation: cp-glitch 260ms steps(3, jump-none) 1;
}
@keyframes cp-glitch {
0%,
100% {
transform: translate(0, 0) skewX(0deg);
}
25% {
transform: translate(-2px, 1px) skewX(-6deg);
}
50% {
transform: translate(3px, -1px) skewX(3deg);
}
75% {
transform: translate(-1px, 0) skewX(-2deg);
}
}
/* Corruption: completed to-dos glitch out before they fade/drop away. */
html.theme-cyberpunk .line-through {
animation: cp-corrupt 450ms steps(6, jump-none) 1;
}
@keyframes cp-corrupt {
0% {
transform: translate(0, 0);
text-shadow: none;
}
15% {
transform: translate(-3px, 1px) skewX(-8deg);
text-shadow:
3px 0 rgb(255 43 214 / 0.9),
-3px 0 rgb(34 255 238 / 0.9);
}
35% {
transform: translate(4px, -1px) skewX(5deg);
text-shadow:
-4px 0 rgb(34 255 238 / 0.9),
4px 0 rgb(255 43 214 / 0.9);
}
55% {
transform: translate(-2px, 1px);
text-shadow:
2px 0 rgb(255 43 214 / 0.8),
-2px 0 rgb(34 255 238 / 0.8);
opacity: 0.7;
}
75% {
transform: translate(2px, -1px) skewX(-3deg);
text-shadow:
-2px 0 rgb(255 43 214 / 0.7),
2px 0 rgb(34 255 238 / 0.7);
}
100% {
transform: translate(0, 0);
text-shadow: none;
opacity: 1;
}
}
/* To-do checkbox: a neon terminal box -- faint scanline texture on the empty
box, a glow that builds on hover, and a full bloom the moment it's checked.
(The check's own stroke/fill already come from the group's accent color.) */
html.theme-cyberpunk [data-todo-checkbox] {
border-radius: 2px;
}
html.theme-cyberpunk [data-todo-checkbox]:not([aria-checked="true"]) {
background-image: repeating-linear-gradient(
0deg,
rgb(34 255 238 / 0.07) 0px,
rgb(34 255 238 / 0.07) 1px,
transparent 1px,
transparent 3px
);
}
html.theme-cyberpunk [data-todo-checkbox]:hover {
box-shadow: 0 0 10px rgb(34 255 238 / 0.5);
}
html.theme-cyberpunk [data-todo-checkbox][aria-checked="true"] {
box-shadow: 0 0 12px rgb(34 255 238 / 0.6);
}
html.theme-cyberpunk [data-todo-checkbox] svg {
filter: drop-shadow(0 0 3px rgb(34 255 238 / 0.85));
}
/* The whole card glitches every so often -- a brief RGB-split, a move, and 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
phase-offset so a boardful of them don't all tear on the same beat. */
html.theme-cyberpunk [data-group-card] {
animation: cp-card-glitch 7s steps(1, end) infinite;
will-change: transform, filter;
}
html.theme-cyberpunk [data-group-card]:nth-child(2n) {
animation-delay: -3.5s;
}
html.theme-cyberpunk [data-group-card]:nth-child(3n) {
animation-delay: -1.7s;
}
@keyframes cp-card-glitch {
0%,
86%,
93%,
100% {
/* rest: no properties set -> the card keeps its natural transform,
filter, clip and shadow (incl. hover lift) between bursts */
}
87% {
transform: translate(-2px, 1px) skewX(-3deg);
filter: saturate(1.6) hue-rotate(-16deg);
box-shadow:
3px 0 rgb(255 43 214 / 0.55),
-3px 0 rgb(34 255 238 / 0.55);
}
88% {
transform: translate(3px, -1px);
filter: saturate(1.8);
box-shadow:
-3px 0 rgb(255 43 214 / 0.55),
3px 0 rgb(34 255 238 / 0.55);
}
89% {
transform: translate(-1px, 1px) skewX(2deg);
filter: hue-rotate(14deg) saturate(1.5);
}
90% {
transform: translate(2px, -1px);
filter: saturate(1.4);
box-shadow:
-4px 0 rgb(255 43 214 / 0.5),
4px 0 rgb(34 255 238 / 0.5);
}
91% {
transform: translate(-2px, 0) skewX(-2deg);
filter: hue-rotate(14deg);
}
92% {
transform: translate(1px, 1px);
filter: saturate(1.4);
}
}
/* ------------------------------ Cyberpunk Markdown Terminal ------------------- */
/* Markdown preview in the notes dialog: a CRT terminal screen with phosphor-
green text on a deep black backdrop. The VT323 pixel face (already scoped
to this theme's --font-sans) carries the whole retro feel. */
html.theme-cyberpunk .wmde-markdown {
font-family: var(--font-cyberpunk), ui-monospace, monospace;
color: #00ff41;
background: oklch(0.06 0.01 140);
text-shadow:
0 0 4px rgb(0 255 65 / 0.35),
0 0 12px rgb(0 255 65 / 0.12);
font-size: 0.8125rem;
letter-spacing: 0.02em;
line-height: 1.65;
}
/* Editor chrome: the toolbar and editing surface inherit the terminal look.
Toolbar sits on a slightly brighter black; the editing surface is pure
phosphor-black with a faint scanline overlay. */
html.theme-cyberpunk .w-md-editor {
font-family: var(--font-cyberpunk), ui-monospace, monospace;
--md-editor-font-family: var(--font-cyberpunk), ui-monospace, monospace;
color: #00ff41;
background: oklch(0.06 0.01 140);
border-color: #00ff41 / 22%;
text-shadow: 0 0 4px rgb(0 255 65 / 0.3);
}
html.theme-cyberpunk .w-md-editor .w-md-editor-toolbar {
background: oklch(0.09 0.01 140);
border-color: #00ff41 / 18%;
box-shadow: 0 0 8px rgb(0 255 65 / 0.08);
}
html.theme-cyberpunk .w-md-editor-toolbar-item,
html.theme-cyberpunk .w-md-editor-toolbar-item-icon {
color: #00cc33;
}
html.theme-cyberpunk .w-md-editor-toolbar-item-active,
html.theme-cyberpunk .w-md-editor-toolbar-item-active .w-md-editor-toolbar-item-icon {
color: #00ff41;
text-shadow: 0 0 6px rgb(0 255 65 / 0.6);
}
html.theme-cyberpunk .w-md-editor-text,
html.theme-cyberpunk .w-md-editor-text-pre,
html.theme-cyberpunk .w-md-editor-text-input {
color: #00ff41;
background: transparent;
font-family: var(--font-cyberpunk), ui-monospace, monospace;
text-shadow: 0 0 4px rgb(0 255 65 / 0.3);
}
html.theme-cyberpunk .w-md-editor-text-input::placeholder {
color: #00cc33 / 40%;
}
/* Subtle CRT scanline texture over the editor surface (not the toolbar).
Fixed-position so it stays anchored to the screen, not the scrolling text.
Click-through via pointer-events so the textarea stays usable. */
html.theme-cyberpunk .w-md-editor-text-wrapper::before {
content: "";
position: absolute;
inset: 0;
pointer-events: none;
z-index: 5;
background: repeating-linear-gradient(
0deg,
rgb(0 255 65 / 0.02) 0px,
rgb(0 255 65 / 0.02) 1px,
transparent 1px,
transparent 3px
);
}
/* Links glow a softer cyan-green so they stand out from body text, and the
terminal cursor (caret) gets a phosphor-green flicker on focus. */
html.theme-cyberpunk .wmde-markdown a,
html.theme-cyberpunk .w-md-editor a {
color: #33ffaa;
text-shadow: 0 0 6px rgb(51 255 170 / 0.4);
}
html.theme-cyberpunk .wmde-markdown code,
html.theme-cyberpunk .w-md-editor-text-pre code,
html.theme-cyberpunk .w-md-editor-text-pre {
background: oklch(0.1 0.015 140);
color: #00ff41;
border: 1px solid #00ff41 / 20%;
text-shadow: 0 0 5px rgb(0 255 65 / 0.4);
}
html.theme-cyberpunk .wmde-markdown pre,
html.theme-cyberpunk .w-md-editor-text-pre {
background: oklch(0.05 0.005 140);
border-color: #00ff41 / 15%;
}
html.theme-cyberpunk .wmde-markdown blockquote {
border-color: #00ff41 / 30%;
color: #00cc33;
}
html.theme-cyberpunk .wmde-markdown hr {
background: #00ff41 / 25%;
box-shadow: 0 0 8px rgb(0 255 65 / 0.2);
}
html.theme-cyberpunk .wmde-markdown h1,
html.theme-cyberpunk .wmde-markdown h2,
html.theme-cyberpunk .wmde-markdown h3,
html.theme-cyberpunk .wmde-markdown h4,
html.theme-cyberpunk .wmde-markdown h5,
html.theme-cyberpunk .wmde-markdown h6 {
color: #00ff41;
text-shadow:
0 0 6px rgb(0 255 65 / 0.5),
0 0 16px rgb(0 255 65 / 0.2);
letter-spacing: 0.04em;
}
/* Faint screen flicker on the preview pane — a slow, barely-visible pulse
like an old CRT phosphor dimming. Doesn't affect readability. */
html.theme-cyberpunk .wmde-markdown {
animation: terminal-flicker 6s ease-in-out infinite;
}
@keyframes terminal-flicker {
0%, 100% { opacity: 1; }
50% { opacity: 0.97; }
}
/* Cursor caret: a block-style terminal cursor that blinks green. */
html.theme-cyberpunk .w-md-editor-text-input::selection {
background: #00ff41 / 25%;
}
/* ------------------------------ 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%
);
}
/* Rolling scanlines: a fixed overlay over the whole app -- the "monitor"
sits over everything (cards, dialogs, toasts), the same move as cyberpunk's
CRT layer, so the texture is actually visible instead of hiding behind the
content. A 1px plum line every 4px, rolling downward at about 1px/s like a
monitor left on all morning. */
html.theme-vaporwave body::before {
content: "";
position: fixed;
inset: 0;
z-index: 999;
pointer-events: none;
background-image: repeating-linear-gradient(
0deg,
oklch(0.35 0.16 330 / 0.06) 0px,
oklch(0.35 0.16 330 / 0.06) 1px,
transparent 1px,
transparent 4px
);
animation: vw-roll 4s linear infinite;
}
@keyframes vw-roll {
from {
background-position-y: 0px;
}
to {
background-position-y: 4px;
}
}
/* The striped synth sun: the vaporwave icon, fixed in the sky behind the
content (it shows through the translucent lanes like light through glass).
Big and low, sitting on the outrun floor's horizon line. Solid across the
top, classic horizontal slats below, the slats drifting slowly downward
like the sun melting toward the horizon. Muted pastels close to the sky's
own lightness, so it reads as part of the sky rather than a sticker on it. */
html.theme-vaporwave body::after {
content: "";
position: fixed;
left: 50%;
bottom: 7vh;
width: 320px;
height: 320px;
z-index: -1;
pointer-events: none;
border-radius: 50%;
transform: translateX(-50%);
background: linear-gradient(
180deg,
oklch(0.93 0.055 90) 0%,
oklch(0.91 0.075 48) 38%,
oklch(0.89 0.09 30) 68%,
oklch(0.86 0.085 350) 100%
);
filter: drop-shadow(0 0 26px oklch(0.85 0.1 40 / 0.3));
-webkit-mask-image: linear-gradient(180deg, #000 0 55%, rgba(0, 0, 0, 0) 55%),
repeating-linear-gradient(180deg, #000 0 10px, rgba(0, 0, 0, 0) 10px 18px);
mask-image: linear-gradient(180deg, #000 0 55%, rgba(0, 0, 0, 0) 55%),
repeating-linear-gradient(180deg, #000 0 10px, rgba(0, 0, 0, 0) 10px 18px);
animation: vw-sun 5s linear infinite;
}
@keyframes vw-sun {
from {
-webkit-mask-position: 0 0, 0 0;
mask-position: 0 0, 0 0;
}
to {
-webkit-mask-position: 0 0, 0 18px;
mask-position: 0 0, 0 18px;
}
}
/* The outrun floor: a perspective grid across the bottom of the viewport,
behind the content (it shows through the translucent lanes). The horizontal
lines crawl toward the viewer while the verticals converge on the
vanishing point. Rendered by the .vw-floor element in app/layout.tsx,
visible only under this theme. */
.vw-floor {
display: none;
}
html.theme-vaporwave .vw-floor {
display: block;
position: fixed;
left: 50%;
bottom: 0;
width: 200vw;
height: 75vh;
z-index: -1;
pointer-events: none;
transform: translateX(-50%) perspective(300px) rotateX(60deg);
transform-origin: 50% 100%;
opacity: 0.8;
background-image:
repeating-linear-gradient(90deg, oklch(0.62 0.25 350 / 0.5) 0 2px, transparent 2px 90px),
repeating-linear-gradient(0deg, oklch(0.62 0.25 350 / 0.5) 0 2px, transparent 2px 44px);
-webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 35%);
mask-image: linear-gradient(180deg, transparent 0%, #000 35%);
animation: vw-floor 2.2s linear infinite;
}
@keyframes vw-floor {
from {
background-position: 0 0, 0 0;
}
to {
background-position: 0 0, 0 44px;
}
}
/* Palm silhouettes: a couple of minimal palms rooted at either side of the
horizon -- the classic vaporwave framing, kept faint so they read as
scenery, not stickers. Drawn as stroked arcs in the .vw-palm SVGs in
app/layout.tsx; they paint above the floor grid (DOM order) but stay
behind the content. Visible only under this theme. */
.vw-palm {
display: none;
}
.vw-palm-defs {
position: absolute;
width: 0;
height: 0;
overflow: hidden;
}
html.theme-vaporwave .vw-palm {
display: block;
position: fixed;
bottom: 1vh;
z-index: -1;
pointer-events: none;
color: oklch(0.47 0.12 325);
}
html.theme-vaporwave .vw-palm--left-main {
left: 18vw;
width: 150px;
height: 187px;
opacity: 0.5;
}
html.theme-vaporwave .vw-palm--left-small {
left: 26vw;
width: 90px;
height: 112px;
opacity: 0.3;
}
html.theme-vaporwave .vw-palm--right-main {
right: 2vw;
width: 150px;
height: 187px;
opacity: 0.5;
transform: scaleX(-1);
}
html.theme-vaporwave .vw-palm--right-small {
right: 10vw;
width: 90px;
height: 112px;
opacity: 0.3;
transform: scaleX(-1);
}
/* VHS hiccup: every so often a card drops out of the signal for half a
second -- a 1-2px jitter, a red/cyan split on the title, and a tracking
band sweeping down the panel, all inside one short window (the first 5%
of each cycle). Cards run three alternating phases with different periods
and offsets, so the board flickers organically instead of in lockstep.
The :not(.opacity-50) guard matters: while dnd-kit drives a drag it sets
an inline `transform` on the card, and a running animation would override
that inline value (animations sit above inline styles in the cascade) --
the card stops following the pointer. opacity-50 is exactly the class the
card gets while dragging, so the hiccup stands down for the duration.
(overflow: hidden keeps the tracking band clipped to the card while it
sweeps; the hover lift uses the separate `translate` property, so the
jitter doesn't fight it.) */
html.theme-vaporwave [data-group-card]:not(.opacity-50) {
overflow: hidden;
animation: vw-card-glitch 10s linear infinite;
}
html.theme-vaporwave [data-group-card]:not(.opacity-50) > div:first-child h3 {
animation: vw-title-glitch 10s linear infinite;
}
html.theme-vaporwave [data-group-card]:not(.opacity-50)::after {
content: "";
position: absolute;
left: 0;
right: 0;
top: -12%;
height: 12px;
opacity: 0;
pointer-events: none;
background:
repeating-linear-gradient(0deg, oklch(0.45 0.15 330 / 0.28) 0 1px, transparent 1px 3px),
linear-gradient(
180deg,
transparent 0%,
oklch(0.72 0.2 350 / 0.22) 20%,
oklch(0.99 0.01 220 / 0.4) 50%,
oklch(0.78 0.15 200 / 0.22) 80%,
transparent 100%
);
animation: vw-tracking 10s linear infinite;
}
/* Phase B: a longer period and an offset start, so neighbors don't hiccup
together. (Static styles above are the idle state -- before a card's
first delay elapses, and under reduced motion, everything just sits still.) */
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50),
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50) > div:first-child h3,
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50)::after {
animation-duration: 13s;
animation-delay: 3s;
}
/* Phase C: the longest period, offset furthest. */
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50),
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50) > div:first-child h3,
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50)::after {
animation-duration: 17s;
animation-delay: 7s;
}
@keyframes vw-card-glitch {
0%,
5%,
100% {
transform: translateX(0);
}
0.8% {
transform: translateX(-1.5px);
}
1.6% {
transform: translateX(-1.5px);
}
2.4% {
transform: translateX(1px);
}
3.2% {
transform: translateX(1px);
}
4% {
transform: translateX(-0.75px);
}
4.6% {
transform: translateX(0.5px);
}
}
@keyframes vw-title-glitch {
0%,
5%,
100% {
text-shadow: none;
}
0.8% {
text-shadow:
1.5px 0 oklch(0.68 0.2 350 / 0.55),
-1.5px 0 oklch(0.85 0.15 200 / 0.55);
}
1.6% {
text-shadow:
-1.5px 0 oklch(0.68 0.2 350 / 0.55),
1.5px 0 oklch(0.85 0.15 200 / 0.55);
}
2.4% {
text-shadow:
1px 0 oklch(0.68 0.2 350 / 0.55),
-1px 0 oklch(0.85 0.15 200 / 0.55);
}
3.2% {
text-shadow:
-0.5px 0 oklch(0.68 0.2 350 / 0.55),
0.5px 0 oklch(0.85 0.15 200 / 0.55);
}
}
@keyframes vw-tracking {
0% {
top: -12%;
opacity: 0;
}
0.8% {
opacity: 0.85;
}
4.8% {
opacity: 0.85;
}
5%,
100% {
top: 112%;
opacity: 0;
}
}
/* 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));
}
/* The lane is the notebook page itself: white paper over the warm desk with
the classic ruling -- blue lines + a red margin rule running down the left
(inside the lane's own padding, so the post-its never cover it). Group
cards sit on top as post-its (below), so the ruling shows around them. */
html.theme-notebook [data-category-lane] {
background-color: oklch(0.978 0.008 90);
background-image:
linear-gradient(90deg, transparent 6px, oklch(0.6 0.19 25 / 0.4) 6px 8px, transparent 8px),
repeating-linear-gradient(180deg, transparent 0 27px, oklch(0.68 0.09 250 / 0.4) 27px 28px);
box-shadow:
0 1px 2px rgb(96 74 40 / 0.14),
0 10px 24px -10px rgb(96 74 40 / 0.3);
}
/* Group cards are post-its stuck onto the page: a slightly darker adhesive
band along the top, and a soft lift shadow that runs heavier to one side,
like a sheet curling off the paper. (:not(.ring-2) keeps the drag
drop-target ring -- a box-shadow utility -- from being overpainted.) */
html.theme-notebook [data-group-card] {
border-width: 2px;
background-image: linear-gradient(180deg, rgb(96 74 40 / 0.07) 0 15%, transparent 15%);
}
html.theme-notebook [data-group-card]:not(.ring-2) {
box-shadow:
1px 1px 2px rgb(96 74 40 / 0.12),
6px 9px 16px -6px rgb(96 74 40 / 0.32);
}
html.theme-notebook [data-group-card]:not(.ring-2):hover {
box-shadow:
1px 2px 3px rgb(96 74 40 / 0.14),
8px 12px 20px -6px rgb(96 74 40 / 0.4);
}
/* A post-it is never stuck perfectly straight: alternate a hair of tilt down
the column so a boardful don't all lean the same way. (While a card is
being dragged, dnd-kit's inline transform overrides this -- the post-it
straightens out in your hand.) */
html.theme-notebook [data-category-lane] .overflow-y-auto > div:nth-child(2n) [data-group-card] {
transform: rotate(0.4deg);
}
html.theme-notebook [data-category-lane] .overflow-y-auto > div:nth-child(2n + 1) [data-group-card] {
transform: rotate(-0.4deg);
}
/* Hand-cut paper edges: the classic uneven border-radius so pages, cards, and
dialogs look drawn by hand instead of machine-rounded. */
html.theme-notebook [data-category-lane] {
border-radius: 170px 10px 150px 10px / 10px 150px 10px 170px;
}
html.theme-notebook [data-slot="card"],
html.theme-notebook [data-slot="dialog-content"],
html.theme-notebook [data-group-card] {
border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
}
/* 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%;
}
}
/* Then a red pen draws a quick check at the end of the line -- grading the
homework. (Scoped to the board's to-do rows: the title button is a flex
row, so the check rides at its right end. It starts fully clipped and
reveals left-to-right, timed to land as the highlighter sweep finishes.) */
html.theme-notebook [data-group-card] .line-through::after {
content: "✓";
flex: none;
margin-left: 2px;
color: oklch(0.55 0.22 27 / 0.95);
font-size: 1.15em;
line-height: 1;
transform: translateY(-1px);
clip-path: inset(-25% 100% -25% 0);
animation: nb-check 300ms ease-out 300ms forwards;
pointer-events: none;
}
@keyframes nb-check {
to {
clip-path: inset(-25% -5% -25% 0);
}
}
/* The global reduced-motion guard kills the reveal animation -- fall back to
the check simply sitting there, already drawn. */
@media (prefers-reduced-motion: reduce) {
html.theme-notebook [data-group-card] .line-through::after {
clip-path: none;
}
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
/* Gentle, calm type for a tool that sits on screen all day. */
font-feature-settings: "cv02", "cv03", "cv04", "cv11";
letter-spacing: -0.006em;
}
/* Headings use the display face (see --font-heading / Figtree). */
h1,
h2,
h3,
h4 {
letter-spacing: -0.018em;
}
/* Smooth, low-key hover/selection feel: fade color changes instead of
snapping. Components that set their own transition-* utility override
this (utilities win on specificity). */
*,
*::before,
*::after {
transition:
background-color 200ms ease,
border-color 200ms ease,
color 200ms ease,
fill 200ms ease,
stroke 200ms ease;
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
transition: none !important;
animation: none !important;
}
}
::selection {
background: color-mix(in srgb, var(--ring) 28%, transparent);
}
/* Quiet scrollbars that match the theme. */
* {
scrollbar-width: thin;
scrollbar-color: color-mix(in srgb, var(--foreground) 22%, transparent) transparent;
}
*::-webkit-scrollbar {
width: 10px;
height: 10px;
}
*::-webkit-scrollbar-track,
*::-webkit-scrollbar-corner {
background: transparent;
}
*::-webkit-scrollbar-thumb {
background: color-mix(in srgb, var(--foreground) 20%, transparent);
border: 3px solid transparent;
border-radius: 999px;
background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover {
background: color-mix(in srgb, var(--foreground) 32%, transparent);
background-clip: padding-box;
}
}
/* ---------------------------------------------------------------------------
Markdown editor / preview (third-party CSS) -- fit the theme's tokens and
the app's type scale so notes blend into dialogs instead of looking
pasted in.
--------------------------------------------------------------------------- */
.wmde-markdown {
font-family: var(--font-sans);
font-size: 0.875rem;
letter-spacing: -0.006em;
}
.w-md-editor {
--md-editor-font-family: var(--font-sans);
font-size: 0.875rem;
color: var(--foreground);
background: var(--card);
border-color: var(--border);
box-shadow: none;
}
.w-md-editor .w-md-editor-toolbar {
background: color-mix(in srgb, var(--foreground) 5%, transparent);
border-color: var(--border);
}
.w-md-editor-toolbar-item,
.w-md-editor-toolbar-item-icon {
color: var(--muted-foreground);
}
.w-md-editor-toolbar-item-active,
.w-md-editor-toolbar-item-active .w-md-editor-toolbar-item-icon {
color: var(--foreground);
}
.w-md-editor-text,
.w-md-editor-text-pre,
.w-md-editor-text-input {
color: var(--foreground);
}
.w-md-editor-text-input::placeholder {
color: var(--muted-foreground);
}
/* Dark-surfaced themes (Dark, Ocean) -- the editor's stock CSS is
light-only, so override it where we render with data-color-mode="dark". */
[data-color-mode="dark"] .w-md-editor {
background: var(--card);
border-color: var(--border);
}
[data-color-mode="dark"] .w-md-editor .w-md-editor-toolbar {
background: color-mix(in srgb, var(--foreground) 7%, transparent);
border-color: var(--border);
}
[data-color-mode="dark"] .w-md-editor .w-md-editor-text,
[data-color-mode="dark"] .w-md-editor .w-md-editor-text-pre,
[data-color-mode="dark"] .w-md-editor .w-md-editor-text-input {
color: var(--foreground);
background: transparent;
}