|
|
|
|
@ -5,9 +5,9 @@
|
|
|
|
|
@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) all
|
|
|
|
|
turn on dark utilities. */
|
|
|
|
|
@custom-variant dark (&:is(.dark *, .ocean *, .theme-pine *, .theme-plum *, .theme-midnight *, .theme-ember *, .theme-rosewood *));
|
|
|
|
|
the dark looks (Dark, Ocean, Pine, Plum, Midnight, Ember, Rosewood,
|
|
|
|
|
Cyberpunk) all turn on dark utilities. */
|
|
|
|
|
@custom-variant dark (&:is(.dark *, .ocean *, .theme-pine *, .theme-plum *, .theme-midnight *, .theme-ember *, .theme-rosewood *, .theme-cyberpunk *));
|
|
|
|
|
|
|
|
|
|
@theme inline {
|
|
|
|
|
--color-background: var(--background);
|
|
|
|
|
@ -59,7 +59,7 @@
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
|
|
|
Themes
|
|
|
|
|
The app ships fourteen looks, chosen via the theme picker:
|
|
|
|
|
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
|
|
|
|
|
@ -68,6 +68,9 @@
|
|
|
|
|
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
|
|
|
|
|
@ -76,8 +79,12 @@
|
|
|
|
|
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.
|
|
|
|
|
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,
|
|
|
|
|
@ -169,12 +176,12 @@
|
|
|
|
|
--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.58 0.19 42);
|
|
|
|
|
--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.54 0.045 58);
|
|
|
|
|
--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);
|
|
|
|
|
@ -191,7 +198,7 @@
|
|
|
|
|
--radius: 0.9rem;
|
|
|
|
|
--sidebar: oklch(0.958 0.013 75);
|
|
|
|
|
--sidebar-foreground: oklch(0.27 0.032 52);
|
|
|
|
|
--sidebar-primary: oklch(0.58 0.19 42);
|
|
|
|
|
--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);
|
|
|
|
|
@ -250,12 +257,12 @@
|
|
|
|
|
--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.55 0.16 155);
|
|
|
|
|
--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.53 0.04 150);
|
|
|
|
|
--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);
|
|
|
|
|
@ -271,7 +278,7 @@
|
|
|
|
|
--radius: 0.8rem;
|
|
|
|
|
--sidebar: oklch(0.965 0.01 145);
|
|
|
|
|
--sidebar-foreground: oklch(0.26 0.03 150);
|
|
|
|
|
--sidebar-primary: oklch(0.55 0.16 155);
|
|
|
|
|
--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);
|
|
|
|
|
@ -290,12 +297,12 @@
|
|
|
|
|
--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.6 0.16 70);
|
|
|
|
|
--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.55 0.05 82);
|
|
|
|
|
--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);
|
|
|
|
|
@ -312,7 +319,7 @@
|
|
|
|
|
--radius: 0.85rem;
|
|
|
|
|
--sidebar: oklch(0.962 0.02 95);
|
|
|
|
|
--sidebar-foreground: oklch(0.28 0.04 80);
|
|
|
|
|
--sidebar-primary: oklch(0.6 0.16 70);
|
|
|
|
|
--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);
|
|
|
|
|
@ -337,7 +344,7 @@
|
|
|
|
|
--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.54 0.045 12);
|
|
|
|
|
--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. */
|
|
|
|
|
@ -379,7 +386,7 @@
|
|
|
|
|
--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.54 0.045 305);
|
|
|
|
|
--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);
|
|
|
|
|
@ -645,6 +652,561 @@
|
|
|
|
|
--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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
|
|
|
EXTRA THEMES -- beyond tokens, Blueprint and Cyberpunk 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).
|
|
|
|
|
--------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/* ------------------------------ 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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 skew, and a
|
|
|
|
|
sliced clip, then it settles back. 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);
|
|
|
|
|
clip-path: inset(0 0 14% 0);
|
|
|
|
|
filter: saturate(1.8);
|
|
|
|
|
}
|
|
|
|
|
89% {
|
|
|
|
|
transform: translate(-1px, 1px) skewX(2deg);
|
|
|
|
|
clip-path: inset(12% 0 0 0);
|
|
|
|
|
}
|
|
|
|
|
90% {
|
|
|
|
|
transform: translate(2px, -1px);
|
|
|
|
|
clip-path: inset(6% 0 18% 0);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@layer base {
|
|
|
|
|
* {
|
|
|
|
|
@apply border-border outline-ring/50;
|
|
|
|
|
|