Skip to content

Commit e1526eb

Browse files
committed
refactor(core): split theme.css into per-theme files
Extract token definitions and structural overrides into individual files under src/assets/themes/ (light, dark, cream, bloom). Each branded theme (cream/bloom) is now fully self-contained with its own gradient, squircle, and transparency rules. theme.css becomes a lightweight hub: @import directives + @theme inline bridge. globals.css retains only theme-agnostic global rules.
1 parent 523c624 commit e1526eb

6 files changed

Lines changed: 363 additions & 284 deletions

File tree

packages/core/src/assets/theme.css

Lines changed: 7 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -1,209 +1,13 @@
1-
@custom-variant dark (&:where(.dark, .dark *));
2-
3-
:root {
4-
--background: rgba(250, 250, 250, 1);
5-
--foreground: rgba(10, 10, 10, 1);
6-
--card: rgba(255, 255, 255, 1);
7-
--card-foreground: rgba(10, 10, 10, 1);
8-
--popover: rgba(255, 255, 255, 1);
9-
--popover-foreground: rgba(10, 10, 10, 1);
10-
--primary: rgba(23, 23, 23, 1);
11-
--primary-foreground: rgba(250, 250, 250, 1);
12-
--secondary: rgba(245, 245, 245, 1);
13-
--secondary-foreground: rgba(23, 23, 23, 1);
14-
--muted: rgba(245, 245, 245, 1);
15-
--muted-foreground: rgba(115, 115, 115, 1);
16-
--accent: rgba(245, 245, 245, 1);
17-
--accent-foreground: rgba(23, 23, 23, 1);
18-
--destructive: rgba(220, 38, 38, 1);
19-
--destructive-foreground: rgba(254, 242, 242, 1);
20-
--border: rgba(229, 229, 229, 1);
21-
--input: rgba(229, 229, 229, 1);
22-
--ring: rgba(163, 163, 163, 1);
23-
--chart-1: rgba(234, 88, 12, 1);
24-
--chart-2: rgba(13, 148, 136, 1);
25-
--chart-3: rgba(22, 78, 99, 1);
26-
--chart-4: rgba(251, 191, 36, 1);
27-
--chart-5: rgba(245, 158, 11, 1);
28-
--radius: 0.625rem;
29-
--sidebar: rgba(250, 250, 250, 1);
30-
--sidebar-foreground: rgba(10, 10, 10, 1);
31-
--sidebar-primary: rgba(23, 23, 23, 1);
32-
--sidebar-primary-foreground: rgba(250, 250, 250, 1);
33-
--sidebar-accent: rgba(245, 245, 245, 1);
34-
--sidebar-accent-foreground: rgba(23, 23, 23, 1);
35-
--sidebar-border: rgba(229, 229, 229, 1);
36-
--sidebar-ring: rgba(163, 163, 163, 1);
37-
/* Status (overridable per theme) */
38-
--status-default: #737373;
39-
--status-neutral: #0ea5e9;
40-
--status-completed: #22c55e;
41-
--status-attention: #f59e0b;
42-
--status-danger: #ef4444;
43-
/* Elevation (wired through @theme; override per Tailor palettes) */
44-
--semantic-shadow-xs: 0 1px 2px 0 rgb(15 23 42 / 0.06);
45-
--semantic-shadow-sm: 0 1px 3px 0 rgb(15 23 42 / 0.08), 0 1px 2px -1px rgb(15 23 42 / 0.08);
46-
--semantic-shadow-md: 0 4px 6px -1px rgb(15 23 42 / 0.09), 0 2px 4px -2px rgb(15 23 42 / 0.06);
47-
--semantic-shadow-lg: 0 10px 15px -3px rgb(15 23 42 / 0.12), 0 4px 6px -4px rgb(15 23 42 / 0.09);
48-
}
49-
50-
.dark {
51-
color-scheme: dark;
52-
--background: rgba(10, 10, 10, 1);
53-
--foreground: rgba(250, 250, 250, 1);
54-
--card: rgba(23, 23, 23, 1);
55-
--card-foreground: rgba(250, 250, 250, 1);
56-
--popover: rgba(38, 38, 38, 1);
57-
--popover-foreground: rgba(250, 250, 250, 1);
58-
--primary: rgba(229, 229, 229, 1);
59-
--primary-foreground: rgba(23, 23, 23, 1);
60-
--secondary: rgba(38, 38, 38, 1);
61-
--secondary-foreground: rgba(250, 250, 250, 1);
62-
--muted: rgba(38, 38, 38, 1);
63-
--muted-foreground: rgba(163, 163, 163, 1);
64-
--accent: rgba(64, 64, 64, 1);
65-
--accent-foreground: rgba(250, 250, 250, 1);
66-
--destructive: rgba(248, 113, 113, 1);
67-
--destructive-foreground: rgba(254, 242, 242, 1);
68-
--border: rgba(255, 255, 255, 0.10000000149011612);
69-
--input: rgba(255, 255, 255, 0.15000000596046448);
70-
--ring: rgba(115, 115, 115, 1);
71-
--chart-1: rgba(29, 78, 216, 1);
72-
--chart-2: rgba(16, 185, 129, 1);
73-
--chart-3: rgba(245, 158, 11, 1);
74-
--chart-4: rgba(168, 85, 247, 1);
75-
--chart-5: rgba(244, 63, 94, 1);
76-
/* Match --background so sidebar blends with the app surface. */
77-
--sidebar: rgba(10, 10, 10, 1);
78-
--sidebar-foreground: rgba(250, 250, 250, 1);
79-
--sidebar-primary: rgba(29, 78, 216, 1);
80-
--sidebar-primary-foreground: rgba(250, 250, 250, 1);
81-
--sidebar-accent: rgba(38, 38, 38, 1);
82-
--sidebar-accent-foreground: rgba(250, 250, 250, 1);
83-
--sidebar-border: rgba(255, 255, 255, 0.10000000149011612);
84-
--sidebar-ring: rgba(82, 82, 82, 1);
85-
--semantic-shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.35);
86-
--semantic-shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.38), 0 1px 2px -1px rgb(0 0 0 / 0.32);
87-
--semantic-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.35), 0 2px 4px -2px rgb(0 0 0 / 0.28);
88-
--semantic-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.42), 0 4px 6px -4px rgb(0 0 0 / 0.35);
89-
}
90-
91-
/**
92-
* Tailor brand — light palette (Tailor brand guidelines).
93-
* Primary: #535AE8 · Text: #10122B · White: #FFFFFF
94-
* Secondary: Deep Cyan #00979C · Dark Green #013742 · Off-White #F8F3E4 · Neutral #EEEEEE · Light Violet #E2D4FE
95-
*/
96-
html[data-theme="cream"] {
97-
color-scheme: light;
98-
/* Off-white app shell; white cards for elevation */
99-
--background: rgba(248, 243, 228, 1);
100-
/* Shell gradient stops (globals.css): light cream tint at top → white at bottom. */
101-
--shell-gradient-start: color-mix(in srgb, var(--background) 55%, rgb(255, 255, 255));
102-
--shell-gradient-end: rgb(255, 255, 255);
103-
--foreground: rgba(16, 18, 43, 1);
104-
--card: rgba(255, 255, 255, 1);
105-
--card-foreground: rgba(16, 18, 43, 1);
106-
--popover: rgba(255, 255, 255, 1);
107-
--popover-foreground: rgba(16, 18, 43, 1);
108-
--primary: rgba(83, 90, 232, 1);
109-
--primary-foreground: rgba(255, 255, 255, 1);
110-
/* Light violet surfaces; near-black text (match bloom; drop the brand dark-green pairing). */
111-
--secondary: rgba(226, 212, 254, 1);
112-
--secondary-foreground: rgba(16, 18, 43, 1);
113-
/* Row hovers / `bg-muted`: subtle neutral lift (same alpha family as `--border`), not a second brand tint. */
114-
--muted: rgba(0, 0, 0, 0.08);
115-
--muted-foreground: rgba(16, 18, 43, 0.72);
116-
--accent: rgba(226, 212, 254, 1);
117-
--accent-foreground: rgba(16, 18, 43, 1);
118-
/* Destructive matches default light theme so the brand red stays consistent across light/cream/bloom. */
119-
--destructive: rgba(220, 38, 38, 1);
120-
--destructive-foreground: rgba(254, 242, 242, 1);
121-
--border: rgba(0, 0, 0, 0.08);
122-
--input: rgba(0, 0, 0, 0.08);
123-
--ring: rgba(83, 90, 232, 0.45);
124-
--chart-1: rgba(83, 90, 232, 1);
125-
--chart-2: rgba(0, 151, 156, 1);
126-
--chart-3: rgba(1, 55, 66, 1);
127-
--chart-4: rgba(110, 95, 195, 1);
128-
--chart-5: rgba(217, 119, 6, 1);
129-
/* Larger corner scale; squircle overlays via globals.css where supported */
130-
--radius: 1rem;
131-
--sidebar: rgba(248, 243, 228, 1);
132-
--sidebar-foreground: rgba(16, 18, 43, 1);
133-
--sidebar-primary: rgba(83, 90, 232, 1);
134-
--sidebar-primary-foreground: rgba(255, 255, 255, 1);
135-
--sidebar-accent: rgba(226, 212, 254, 1);
136-
--sidebar-accent-foreground: rgba(16, 18, 43, 1);
137-
--sidebar-border: rgba(0, 0, 0, 0.08);
138-
--sidebar-ring: rgba(83, 90, 232, 0.45);
139-
--status-default: rgba(16, 18, 43, 0.55);
140-
--status-neutral: #00979c;
141-
--status-completed: #00979c;
142-
--status-attention: #d97706;
143-
--status-danger: #dc2626;
144-
--semantic-shadow-xs: 0 1px 2px 0 rgb(16 18 43 / 0.07);
145-
--semantic-shadow-sm: 0 1px 3px 0 rgb(16 18 43 / 0.08), 0 1px 2px -1px rgb(16 18 43 / 0.06);
146-
--semantic-shadow-md: 0 4px 6px -1px rgb(16 18 43 / 0.1), 0 2px 4px -2px rgb(16 18 43 / 0.08);
147-
--semantic-shadow-lg: 0 10px 15px -3px rgb(16 18 43 / 0.12), 0 4px 6px -4px rgb(83 90 232 / 0.1);
148-
}
1+
@import "./themes/light.css";
2+
@import "./themes/dark.css";
3+
@import "./themes/cream.css";
4+
@import "./themes/bloom.css";
1495

1506
/**
151-
* Bloom — light lavender app shell; cream secondary/accent surfaces (inverse of Tailor light).
7+
* Tailwind v4 theme bridge — maps raw CSS custom properties to Tailwind's
8+
* design token namespace so utilities like `bg-background`, `text-primary`,
9+
* `shadow-sm` resolve correctly regardless of the active palette.
15210
*/
153-
html[data-theme="bloom"] {
154-
color-scheme: light;
155-
--background: rgba(239, 232, 255, 1);
156-
/* Shell gradient stops (globals.css): light lavender tint at top → white at bottom. */
157-
--shell-gradient-start: color-mix(in srgb, var(--background) 55%, rgb(255, 255, 255));
158-
--shell-gradient-end: rgb(255, 255, 255);
159-
--foreground: rgba(16, 18, 43, 1);
160-
--card: rgba(255, 255, 255, 1);
161-
--card-foreground: rgba(16, 18, 43, 1);
162-
--popover: rgba(255, 255, 255, 1);
163-
--popover-foreground: rgba(16, 18, 43, 1);
164-
--primary: rgba(83, 90, 232, 1);
165-
--primary-foreground: rgba(255, 255, 255, 1);
166-
/* Match light theme — neutral pale grey reads as a soft pill on the lavender shell. */
167-
--secondary: rgba(245, 245, 245, 1);
168-
--secondary-foreground: rgba(23, 23, 23, 1);
169-
/* Row hovers / `bg-muted`: subtle neutral lift (same alpha family as `--border`). */
170-
--muted: rgba(0, 0, 0, 0.08);
171-
--muted-foreground: rgba(16, 18, 43, 0.72);
172-
--accent: rgba(248, 243, 228, 1);
173-
--accent-foreground: rgba(16, 18, 43, 1);
174-
/* Destructive matches default light theme so the brand red stays consistent across light/cream/bloom. */
175-
--destructive: rgba(220, 38, 38, 1);
176-
--destructive-foreground: rgba(254, 242, 242, 1);
177-
--border: rgba(0, 0, 0, 0.08);
178-
--input: rgba(0, 0, 0, 0.08);
179-
--ring: rgba(83, 90, 232, 0.45);
180-
--chart-1: rgba(83, 90, 232, 1);
181-
--chart-2: rgba(0, 151, 156, 1);
182-
--chart-3: rgba(1, 55, 66, 1);
183-
--chart-4: rgba(110, 95, 195, 1);
184-
--chart-5: rgba(217, 119, 6, 1);
185-
--radius: 1rem;
186-
--sidebar: rgba(239, 232, 255, 1);
187-
--sidebar-foreground: rgba(16, 18, 43, 1);
188-
--sidebar-primary: rgba(83, 90, 232, 1);
189-
--sidebar-primary-foreground: rgba(255, 255, 255, 1);
190-
/* White elevated row on lavender shell (readable vs lavender-on-lavender) */
191-
--sidebar-accent: rgba(255, 255, 255, 1);
192-
--sidebar-accent-foreground: rgba(16, 18, 43, 1);
193-
--sidebar-border: rgba(0, 0, 0, 0.08);
194-
--sidebar-ring: rgba(83, 90, 232, 0.45);
195-
--status-default: rgba(16, 18, 43, 0.55);
196-
/* Bloom: teal + violet-tint foregrounds; amber + dusty rose harmonize with shell */
197-
--status-neutral: #0b8c9a;
198-
--status-completed: #0d7668;
199-
--status-attention: #ae6f12;
200-
--status-danger: #ae2438;
201-
--semantic-shadow-xs: 0 1px 2px 0 rgb(16 18 43 / 0.07);
202-
--semantic-shadow-sm: 0 1px 3px 0 rgb(16 18 43 / 0.08), 0 1px 2px -1px rgb(16 18 43 / 0.06);
203-
--semantic-shadow-md: 0 4px 6px -1px rgb(16 18 43 / 0.1), 0 2px 4px -2px rgb(16 18 43 / 0.08);
204-
--semantic-shadow-lg: 0 10px 15px -3px rgb(16 18 43 / 0.12), 0 4px 6px -4px rgb(83 90 232 / 0.1);
205-
}
206-
20711
@theme inline {
20812
--color-background: var(--background);
20913
--color-foreground: var(--foreground);
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* Bloom — light lavender app shell; cream secondary/accent surfaces (inverse of Tailor light).
3+
*/
4+
html[data-theme="bloom"] {
5+
color-scheme: light;
6+
--background: rgba(239, 232, 255, 1);
7+
/* Shell gradient stops (globals.css): light lavender tint at top → white at bottom. */
8+
--shell-gradient-start: color-mix(in srgb, var(--background) 55%, rgb(255, 255, 255));
9+
--shell-gradient-end: rgb(255, 255, 255);
10+
--foreground: rgba(16, 18, 43, 1);
11+
--card: rgba(255, 255, 255, 1);
12+
--card-foreground: rgba(16, 18, 43, 1);
13+
--popover: rgba(255, 255, 255, 1);
14+
--popover-foreground: rgba(16, 18, 43, 1);
15+
--primary: rgba(83, 90, 232, 1);
16+
--primary-foreground: rgba(255, 255, 255, 1);
17+
/* Match light theme — neutral pale grey reads as a soft pill on the lavender shell. */
18+
--secondary: rgba(245, 245, 245, 1);
19+
--secondary-foreground: rgba(23, 23, 23, 1);
20+
/* Row hovers / `bg-muted`: subtle neutral lift (same alpha family as `--border`). */
21+
--muted: rgba(0, 0, 0, 0.08);
22+
--muted-foreground: rgba(16, 18, 43, 0.72);
23+
--accent: rgba(248, 243, 228, 1);
24+
--accent-foreground: rgba(16, 18, 43, 1);
25+
/* Destructive matches default light theme so the brand red stays consistent across light/cream/bloom. */
26+
--destructive: rgba(220, 38, 38, 1);
27+
--destructive-foreground: rgba(254, 242, 242, 1);
28+
--border: rgba(0, 0, 0, 0.08);
29+
--input: rgba(0, 0, 0, 0.08);
30+
--ring: rgba(83, 90, 232, 0.45);
31+
--chart-1: rgba(83, 90, 232, 1);
32+
--chart-2: rgba(0, 151, 156, 1);
33+
--chart-3: rgba(1, 55, 66, 1);
34+
--chart-4: rgba(110, 95, 195, 1);
35+
--chart-5: rgba(217, 119, 6, 1);
36+
--radius: 1rem;
37+
--sidebar: rgba(239, 232, 255, 1);
38+
--sidebar-foreground: rgba(16, 18, 43, 1);
39+
--sidebar-primary: rgba(83, 90, 232, 1);
40+
--sidebar-primary-foreground: rgba(255, 255, 255, 1);
41+
/* White elevated row on lavender shell (readable vs lavender-on-lavender) */
42+
--sidebar-accent: rgba(255, 255, 255, 1);
43+
--sidebar-accent-foreground: rgba(16, 18, 43, 1);
44+
--sidebar-border: rgba(0, 0, 0, 0.08);
45+
--sidebar-ring: rgba(83, 90, 232, 0.45);
46+
--status-default: rgba(16, 18, 43, 0.55);
47+
/* Bloom: teal + violet-tint foregrounds; amber + dusty rose harmonize with shell */
48+
--status-neutral: #0b8c9a;
49+
--status-completed: #0d7668;
50+
--status-attention: #ae6f12;
51+
--status-danger: #ae2438;
52+
--semantic-shadow-xs: 0 1px 2px 0 rgb(16 18 43 / 0.07);
53+
--semantic-shadow-sm: 0 1px 3px 0 rgb(16 18 43 / 0.08), 0 1px 2px -1px rgb(16 18 43 / 0.06);
54+
--semantic-shadow-md: 0 4px 6px -1px rgb(16 18 43 / 0.1), 0 2px 4px -2px rgb(16 18 43 / 0.08);
55+
--semantic-shadow-lg: 0 10px 15px -3px rgb(16 18 43 / 0.12), 0 4px 6px -4px rgb(83 90 232 / 0.1);
56+
}
57+
58+
/*
59+
* Structural overrides — shell gradient, transparent chrome, squircle corners,
60+
* tighter heading rhythm. These rules give Bloom its distinctive branded look.
61+
*/
62+
63+
@layer base {
64+
/* Vertical shell gradient: light lavender tint at top -> white at bottom. */
65+
html[data-theme="bloom"] {
66+
min-height: 100vh;
67+
min-height: 100dvh;
68+
background-color: var(--background);
69+
background-image: linear-gradient(
70+
to bottom,
71+
var(--shell-gradient-start) 0%,
72+
color-mix(in srgb, var(--background) 45%, white) 20%,
73+
color-mix(in srgb, var(--background) 30%, white) 40%,
74+
color-mix(in srgb, var(--background) 15%, white) 55%,
75+
color-mix(in srgb, var(--background) 6%, white) 65%,
76+
var(--shell-gradient-end) 70%,
77+
var(--shell-gradient-end) 100%
78+
);
79+
background-attachment: fixed;
80+
background-repeat: no-repeat;
81+
background-size: 100% 100%;
82+
}
83+
84+
/* Tighter heading rhythm for branded feel. */
85+
html[data-theme="bloom"] :where(h1, h2, h3, h4, h5, h6) {
86+
letter-spacing: -0.03em;
87+
line-height: 1.2;
88+
}
89+
90+
/* Apple-style squircle corners where engine supports corner-shape (Chromium). */
91+
@supports (corner-shape: squircle) {
92+
html[data-theme="bloom"] * {
93+
corner-shape: squircle;
94+
}
95+
html[data-theme="bloom"] [class*="rounded-full"] {
96+
corner-shape: round;
97+
}
98+
}
99+
}
100+
101+
@layer utilities {
102+
/* Body and sidebar chrome stay transparent so the shell gradient shows through. */
103+
html[data-theme="bloom"] body {
104+
background-color: transparent;
105+
background-image: none;
106+
}
107+
108+
html[data-theme="bloom"] [data-slot="sidebar-wrapper"],
109+
html[data-theme="bloom"] [data-slot="sidebar-inner"],
110+
html[data-theme="bloom"] main[data-slot="sidebar-inset"],
111+
html[data-theme="bloom"]
112+
[data-slot="sidebar"][class*="bg-sidebar"]:not([data-mobile="true"]):not(
113+
[data-icon-mode="true"]
114+
) {
115+
background-color: transparent;
116+
}
117+
118+
/* Outline button: transparent fill so the shell gradient shows through. */
119+
html[data-theme="bloom"] [data-slot="button"][class*="astw:bg-background"][class*="astw:border"] {
120+
background-color: transparent;
121+
transition:
122+
background-color 0.12s ease,
123+
color 0.12s ease;
124+
}
125+
126+
html[data-theme="bloom"]
127+
[data-slot="button"][class*="astw:bg-background"][class*="astw:border"]:hover:not(:disabled) {
128+
background-color: var(--accent);
129+
color: var(--accent-foreground);
130+
}
131+
}

0 commit comments

Comments
 (0)