@cascivo/themes 0.2.6 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 urbanisierung
3
+ Copyright (c) cascivo contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -16,12 +16,54 @@
16
16
 
17
17
  ---
18
18
 
19
- First-party themes for cascivo — 14 of them: `light`, `dark`, `warm`, `midnight`, `pastel`, `brutalist`, `corporate`, `terminal`, `cyberpunk`, and more. Apply via `data-theme` on any container; themes override the semantic token layer only, leaving component and primitive tokens unchanged.
19
+ First-party themes for cascivo — 12 of them, applied with a single `data-theme` attribute. Themes override the **semantic token layer only**, leaving primitive and component tokens unchanged, so every component (and your own token-consuming CSS) restyles for free.
20
+
21
+ ## The themes
22
+
23
+ `light` · `dark` · `warm` · `flat` · `minimal` · `midnight` · `pastel` · `brutalist` · `corporate` · `terminal` · `cyberpunk` · `arcade`
24
+
25
+ ## Import options
26
+
27
+ **Everything (recommended starting point):**
28
+
29
+ ```ts
30
+ import '@cascivo/themes/all' // tokens (once) + base typography + light & dark
31
+ ```
32
+
33
+ **À la carte** — each theme sheet self-imports `@cascivo/tokens` (deduped by URL, so multiple themes load tokens once). Import only what you ship:
34
+
35
+ ```ts
36
+ import '@cascivo/themes/base' // base typography layer (font, line-height, color)
37
+ import '@cascivo/themes/light'
38
+ import '@cascivo/themes/dark'
39
+ import '@cascivo/themes/midnight' // …any of the 12 themes by name
40
+ ```
41
+
42
+ Every export also works with an explicit `.css` suffix (`@cascivo/themes/light.css`) for tooling that requires it.
43
+
44
+ **Tailwind interop:** `@cascivo/themes/tailwind` is a bridging sheet (not a theme) that maps cascivo tokens onto Tailwind theme variables — see [docs/USING-WITH-TAILWIND.md](https://github.com/cascivo/cascivo/blob/main/docs/USING-WITH-TAILWIND.md).
45
+
46
+ ## Scoping with `data-theme`
47
+
48
+ Apply a theme to the whole app or to any container — themes nest, so a dashboard can be `dark` while a preview pane inside it is `light`:
49
+
50
+ ```html
51
+ <body data-theme="dark">
52
+ ...
53
+ <section data-theme="light"><!-- locally light --></section>
54
+ </body>
55
+ ```
56
+
57
+ Only themes whose CSS you imported are available; the attribute value must match the theme name.
20
58
 
21
59
  ## Per-theme fonts
22
60
 
23
61
  A theme can carry its own **display** (headline/brand) face via `--cascivo-font-display`. The token defaults to `var(--cascivo-font-sans)` (so themes that don't override it look unchanged) and is declared in every theme to keep token parity. The `Heading` component renders in the display face, so an override is visible wherever headings appear — e.g. `terminal` maps it to the mono stack and `brutalist` to a heavy grotesk. `--cascivo-font-sans`/`-mono` remain the global body/code defaults.
24
62
 
63
+ ## Custom themes & branding
64
+
65
+ To match a brand, override semantic `--cascivo-*` custom properties in your own CSS (or generate a full theme with the `create_theme` MCP tool / `cascivo` CLI). The layer cascade, the `data-theme` specificity footgun, per-role radius/control-height tokens, and a starter theme are covered in [docs/THEMING.md](https://github.com/cascivo/cascivo/blob/main/docs/THEMING.md).
66
+
25
67
  ## Install
26
68
 
27
69
  ```sh
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cascivo/themes",
3
- "version": "0.2.6",
3
+ "version": "0.2.11",
4
4
  "private": false,
5
5
  "description": "First-party cascivo themes: light, dark, warm, flat, minimal, midnight, pastel, brutalist, corporate, terminal, cyberpunk, arcade",
6
6
  "keywords": [
@@ -54,7 +54,9 @@
54
54
  "./cyberpunk": "./src/cyberpunk.css",
55
55
  "./cyberpunk.css": "./src/cyberpunk.css",
56
56
  "./arcade": "./src/arcade.css",
57
- "./arcade.css": "./src/arcade.css"
57
+ "./arcade.css": "./src/arcade.css",
58
+ "./tailwind": "./src/tailwind.css",
59
+ "./tailwind.css": "./src/tailwind.css"
58
60
  },
59
61
  "publishConfig": {
60
62
  "access": "public",
@@ -64,7 +66,7 @@
64
66
  "@types/node": "^25",
65
67
  "typescript": "^5",
66
68
  "vite-plus": "^0.2.1",
67
- "@cascivo/tokens": "0.3.4"
69
+ "@cascivo/tokens": "0.3.8"
68
70
  },
69
71
  "peerDependencies": {
70
72
  "@cascivo/tokens": ">=0.2.0"
package/readme.body.md CHANGED
@@ -1,5 +1,47 @@
1
- First-party themes for cascivo — 14 of them: `light`, `dark`, `warm`, `midnight`, `pastel`, `brutalist`, `corporate`, `terminal`, `cyberpunk`, and more. Apply via `data-theme` on any container; themes override the semantic token layer only, leaving component and primitive tokens unchanged.
1
+ First-party themes for cascivo — {{count.themes}} of them, applied with a single `data-theme` attribute. Themes override the **semantic token layer only**, leaving primitive and component tokens unchanged, so every component (and your own token-consuming CSS) restyles for free.
2
+
3
+ ## The themes
4
+
5
+ `light` · `dark` · `warm` · `flat` · `minimal` · `midnight` · `pastel` · `brutalist` · `corporate` · `terminal` · `cyberpunk` · `arcade`
6
+
7
+ ## Import options
8
+
9
+ **Everything (recommended starting point):**
10
+
11
+ ```ts
12
+ import '@cascivo/themes/all' // tokens (once) + base typography + light & dark
13
+ ```
14
+
15
+ **À la carte** — each theme sheet self-imports `@cascivo/tokens` (deduped by URL, so multiple themes load tokens once). Import only what you ship:
16
+
17
+ ```ts
18
+ import '@cascivo/themes/base' // base typography layer (font, line-height, color)
19
+ import '@cascivo/themes/light'
20
+ import '@cascivo/themes/dark'
21
+ import '@cascivo/themes/midnight' // …any of the {{count.themes}} themes by name
22
+ ```
23
+
24
+ Every export also works with an explicit `.css` suffix (`@cascivo/themes/light.css`) for tooling that requires it.
25
+
26
+ **Tailwind interop:** `@cascivo/themes/tailwind` is a bridging sheet (not a theme) that maps cascivo tokens onto Tailwind theme variables — see [docs/USING-WITH-TAILWIND.md](https://github.com/cascivo/cascivo/blob/main/docs/USING-WITH-TAILWIND.md).
27
+
28
+ ## Scoping with `data-theme`
29
+
30
+ Apply a theme to the whole app or to any container — themes nest, so a dashboard can be `dark` while a preview pane inside it is `light`:
31
+
32
+ ```html
33
+ <body data-theme="dark">
34
+ ...
35
+ <section data-theme="light"><!-- locally light --></section>
36
+ </body>
37
+ ```
38
+
39
+ Only themes whose CSS you imported are available; the attribute value must match the theme name.
2
40
 
3
41
  ## Per-theme fonts
4
42
 
5
43
  A theme can carry its own **display** (headline/brand) face via `--cascivo-font-display`. The token defaults to `var(--cascivo-font-sans)` (so themes that don't override it look unchanged) and is declared in every theme to keep token parity. The `Heading` component renders in the display face, so an override is visible wherever headings appear — e.g. `terminal` maps it to the mono stack and `brutalist` to a heavy grotesk. `--cascivo-font-sans`/`-mono` remain the global body/code defaults.
44
+
45
+ ## Custom themes & branding
46
+
47
+ To match a brand, override semantic `--cascivo-*` custom properties in your own CSS (or generate a full theme with the `create_theme` MCP tool / `cascivo` CLI). The layer cascade, the `data-theme` specificity footgun, per-role radius/control-height tokens, and a starter theme are covered in [docs/THEMING.md](https://github.com/cascivo/cascivo/blob/main/docs/THEMING.md).
package/src/all.css CHANGED
@@ -13,6 +13,7 @@
13
13
  Component CSS (@cascivo/react/styles.css) adds cascivo.component on top. */
14
14
 
15
15
  @import '@cascivo/tokens';
16
+ @import '@cascivo/tokens/properties.css';
16
17
  @import './base.css';
17
18
  @import './light.css';
18
19
  @import './dark.css';
package/src/arcade.css CHANGED
@@ -34,14 +34,27 @@
34
34
  --cascivo-color-text: var(--cascivo-color-foreground);
35
35
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
36
36
  --cascivo-color-text-muted: oklch(0.52 0.02 265);
37
- --cascivo-color-text-on-accent: oklch(0.98 0 0);
38
- --cascivo-color-text-on-destructive: oklch(0.98 0 0);
39
-
37
+ --cascivo-color-text-on-accent: oklch(0.98 0 0); /* static fallback */
38
+ --cascivo-color-text-on-destructive: oklch(0.98 0 0); /* static fallback */
39
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
40
+ does not honor the static fallback on unsupported browsers — the var()
41
+ substitution keeps the invalid token and the color inherits foreground.
42
+ Guard the upgrade so only supporting browsers apply it. */
43
+ @supports (color: contrast-color(red)) {
44
+ & {
45
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
46
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
47
+ }
48
+ }
40
49
  /* ── Accent — coin-op red ─────────────────────────── */
41
50
  --cascivo-color-accent: oklch(0.55 0.22 27);
42
51
  --cascivo-color-accent-foreground: oklch(0.98 0 0);
43
- --cascivo-color-accent-hover: oklch(0.49 0.23 27);
44
- --cascivo-color-accent-active: oklch(0.44 0.23 27);
52
+ --cascivo-color-accent-hover: oklch(0.49 0.23 27); /* static fallback */
53
+ --cascivo-color-accent-hover: oklch(from var(--cascivo-color-accent) 0.49 0.23 h); /* derived */
54
+ --cascivo-color-accent-active: oklch(0.44 0.23 27); /* static fallback */
55
+ --cascivo-color-accent-active: oklch(
56
+ from var(--cascivo-color-accent) 0.44 0.23 h
57
+ ); /* derived */
45
58
  --cascivo-color-accent-subtle: oklch(0.55 0.22 27 / 0.12);
46
59
  --cascivo-color-accent-muted: oklch(0.55 0.22 27 / 0.2);
47
60
 
@@ -54,7 +67,10 @@
54
67
 
55
68
  /* ── Destructive ──────────────────────────────────── */
56
69
  --cascivo-color-destructive: oklch(0.52 0.24 25);
57
- --cascivo-color-destructive-hover: oklch(0.46 0.24 25);
70
+ --cascivo-color-destructive-hover: oklch(0.46 0.24 25); /* static fallback */
71
+ --cascivo-color-destructive-hover: oklch(
72
+ from var(--cascivo-color-destructive) 0.46 0.24 h
73
+ ); /* derived */
58
74
  --cascivo-color-destructive-subtle: oklch(0.95 0.05 25);
59
75
 
60
76
  /* ── Semantic status colors ───────────────────────── */
@@ -68,6 +84,7 @@
68
84
  --cascivo-color-success-foreground: oklch(0.54 0.18 145);
69
85
  --cascivo-color-warning-foreground: oklch(0.5 0.15 75);
70
86
  --cascivo-color-destructive-foreground: oklch(0.42 0.22 25);
87
+ --cascivo-color-info-foreground: oklch(0.5 0.2 250);
71
88
 
72
89
  /* ── Radius — zero (pixel-blocky) ─────────────────── */
73
90
  --cascivo-radius-base: 0;
package/src/brutalist.css CHANGED
@@ -34,9 +34,18 @@
34
34
  --cascivo-color-text: var(--cascivo-color-foreground);
35
35
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
36
36
  --cascivo-color-text-muted: oklch(0.5 0 0);
37
- --cascivo-color-text-on-accent: oklch(0.1 0 0);
38
- --cascivo-color-text-on-destructive: oklch(1 0 0);
39
-
37
+ --cascivo-color-text-on-accent: oklch(0.1 0 0); /* static fallback */
38
+ --cascivo-color-text-on-destructive: oklch(1 0 0); /* static fallback */
39
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
40
+ does not honor the static fallback on unsupported browsers — the var()
41
+ substitution keeps the invalid token and the color inherits foreground.
42
+ Guard the upgrade so only supporting browsers apply it. */
43
+ @supports (color: contrast-color(red)) {
44
+ & {
45
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
46
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
47
+ }
48
+ }
40
49
  /* ── Accent — acid yellow ─────────────────────────── */
41
50
  --cascivo-color-accent: oklch(0.88 0.19 105);
42
51
  --cascivo-color-accent-foreground: oklch(0.1 0 0);
@@ -54,7 +63,10 @@
54
63
 
55
64
  /* ── Destructive ──────────────────────────────────── */
56
65
  --cascivo-color-destructive: oklch(0.52 0.22 22);
57
- --cascivo-color-destructive-hover: oklch(0.46 0.23 22);
66
+ --cascivo-color-destructive-hover: oklch(0.46 0.23 22); /* static fallback */
67
+ --cascivo-color-destructive-hover: oklch(
68
+ from var(--cascivo-color-destructive) 0.46 0.23 h
69
+ ); /* derived */
58
70
  --cascivo-color-destructive-subtle: oklch(0.95 0.05 22);
59
71
 
60
72
  /* ── Semantic status colors ───────────────────────── */
@@ -68,6 +80,7 @@
68
80
  --cascivo-color-success-foreground: oklch(0.52 0.18 145);
69
81
  --cascivo-color-warning-foreground: oklch(0.5 0.15 75);
70
82
  --cascivo-color-destructive-foreground: oklch(0.4 0.2 22);
83
+ --cascivo-color-info-foreground: oklch(0.45 0.2 250);
71
84
 
72
85
  /* ── Radius — zero ───────────────────────────────── */
73
86
  --cascivo-radius-base: 0;
package/src/corporate.css CHANGED
@@ -34,14 +34,27 @@
34
34
  --cascivo-color-text: var(--cascivo-color-foreground);
35
35
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
36
36
  --cascivo-color-text-muted: oklch(0.65 0.012 255);
37
- --cascivo-color-text-on-accent: oklch(1 0 0);
38
- --cascivo-color-text-on-destructive: oklch(1 0 0);
39
-
37
+ --cascivo-color-text-on-accent: oklch(1 0 0); /* static fallback */
38
+ --cascivo-color-text-on-destructive: oklch(1 0 0); /* static fallback */
39
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
40
+ does not honor the static fallback on unsupported browsers — the var()
41
+ substitution keeps the invalid token and the color inherits foreground.
42
+ Guard the upgrade so only supporting browsers apply it. */
43
+ @supports (color: contrast-color(red)) {
44
+ & {
45
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
46
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
47
+ }
48
+ }
40
49
  /* ── Accent — conservative blue ──────────────────── */
41
50
  --cascivo-color-accent: oklch(0.5 0.16 255);
42
51
  --cascivo-color-accent-foreground: oklch(1 0 0);
43
- --cascivo-color-accent-hover: oklch(0.44 0.17 255);
44
- --cascivo-color-accent-active: oklch(0.38 0.16 255);
52
+ --cascivo-color-accent-hover: oklch(0.44 0.17 255); /* static fallback */
53
+ --cascivo-color-accent-hover: oklch(from var(--cascivo-color-accent) 0.44 0.17 h); /* derived */
54
+ --cascivo-color-accent-active: oklch(0.38 0.16 255); /* static fallback */
55
+ --cascivo-color-accent-active: oklch(
56
+ from var(--cascivo-color-accent) 0.38 0.16 h
57
+ ); /* derived */
45
58
  --cascivo-color-accent-subtle: oklch(0.95 0.03 255);
46
59
  --cascivo-color-accent-muted: oklch(0.9 0.05 255);
47
60
 
@@ -54,7 +67,10 @@
54
67
 
55
68
  /* ── Destructive ──────────────────────────────────── */
56
69
  --cascivo-color-destructive: oklch(0.54 0.19 22);
57
- --cascivo-color-destructive-hover: oklch(0.48 0.2 22);
70
+ --cascivo-color-destructive-hover: oklch(0.48 0.2 22); /* static fallback */
71
+ --cascivo-color-destructive-hover: oklch(
72
+ from var(--cascivo-color-destructive) 0.48 0.2 h
73
+ ); /* derived */
58
74
  --cascivo-color-destructive-subtle: oklch(0.97 0.02 22);
59
75
 
60
76
  /* ── Semantic status colors ───────────────────────── */
@@ -68,6 +84,7 @@
68
84
  --cascivo-color-success-foreground: oklch(0.45 0.14 145);
69
85
  --cascivo-color-warning-foreground: oklch(0.5 0.13 75);
70
86
  --cascivo-color-destructive-foreground: oklch(0.448 0.17 22);
87
+ --cascivo-color-info-foreground: oklch(0.45 0.17 255);
71
88
 
72
89
  /* ── Radius — 2px ────────────────────────────────── */
73
90
  --cascivo-radius-base: 0.125rem;
package/src/cyberpunk.css CHANGED
@@ -34,14 +34,25 @@
34
34
  --cascivo-color-text: var(--cascivo-color-foreground);
35
35
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
36
36
  --cascivo-color-text-muted: oklch(0.55 0.05 300);
37
- --cascivo-color-text-on-accent: oklch(0.16 0.03 285);
38
- --cascivo-color-text-on-destructive: oklch(0.16 0.03 285);
39
-
37
+ --cascivo-color-text-on-accent: oklch(0.16 0.03 285); /* static fallback */
38
+ --cascivo-color-text-on-destructive: oklch(0.16 0.03 285); /* static fallback */
39
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
40
+ does not honor the static fallback on unsupported browsers — the var()
41
+ substitution keeps the invalid token and the color inherits foreground.
42
+ Guard the upgrade so only supporting browsers apply it. */
43
+ @supports (color: contrast-color(red)) {
44
+ & {
45
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
46
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
47
+ }
48
+ }
40
49
  /* ── Accent — neon magenta ───────────────────────── */
41
50
  --cascivo-color-accent: oklch(0.7 0.25 330);
42
51
  --cascivo-color-accent-foreground: oklch(0.16 0.03 285);
43
- --cascivo-color-accent-hover: oklch(0.76 0.23 330);
44
- --cascivo-color-accent-active: oklch(0.82 0.2 330);
52
+ --cascivo-color-accent-hover: oklch(0.76 0.23 330); /* static fallback */
53
+ --cascivo-color-accent-hover: oklch(from var(--cascivo-color-accent) 0.76 0.23 h); /* derived */
54
+ --cascivo-color-accent-active: oklch(0.82 0.2 330); /* static fallback */
55
+ --cascivo-color-accent-active: oklch(from var(--cascivo-color-accent) 0.82 0.2 h); /* derived */
45
56
  --cascivo-color-accent-subtle: oklch(0.7 0.25 330 / 0.12);
46
57
  --cascivo-color-accent-muted: oklch(0.7 0.25 330 / 0.22);
47
58
 
@@ -54,7 +65,10 @@
54
65
 
55
66
  /* ── Destructive — neon red ───────────────────────── */
56
67
  --cascivo-color-destructive: oklch(0.65 0.25 18);
57
- --cascivo-color-destructive-hover: oklch(0.72 0.22 18);
68
+ --cascivo-color-destructive-hover: oklch(0.72 0.22 18); /* static fallback */
69
+ --cascivo-color-destructive-hover: oklch(
70
+ from var(--cascivo-color-destructive) 0.72 0.22 h
71
+ ); /* derived */
58
72
  --cascivo-color-destructive-subtle: oklch(0.65 0.25 18 / 0.12);
59
73
 
60
74
  /* ── Semantic status colors ───────────────────────── */
@@ -68,6 +82,7 @@
68
82
  --cascivo-color-success-foreground: oklch(0.82 0.2 150);
69
83
  --cascivo-color-warning-foreground: oklch(0.82 0.17 75);
70
84
  --cascivo-color-destructive-foreground: oklch(0.78 0.18 18);
85
+ --cascivo-color-info-foreground: oklch(0.82 0.16 200);
71
86
 
72
87
  /* ── Radius — zero ───────────────────────────────── */
73
88
  --cascivo-radius-base: 0;
package/src/dark.css CHANGED
@@ -35,20 +35,38 @@
35
35
  --cascivo-color-text: var(--cascivo-color-foreground);
36
36
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
37
37
  --cascivo-color-text-muted: oklch(0.554 0.018 264);
38
- --cascivo-color-text-on-accent: oklch(0.145 0.005 250);
39
- --cascivo-color-text-on-destructive: oklch(1 0 0);
40
-
38
+ --cascivo-color-text-on-accent: oklch(0.145 0.005 250); /* static fallback */
39
+ --cascivo-color-text-on-destructive: oklch(1 0 0); /* static fallback */
40
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
41
+ does not honor the static fallback on unsupported browsers — the var()
42
+ substitution keeps the invalid token and the color inherits foreground.
43
+ Guard the upgrade so only supporting browsers apply it. */
44
+ @supports (color: contrast-color(red)) {
45
+ & {
46
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
47
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
48
+ }
49
+ }
41
50
  /* ── Accent ───────────────────────────────────────── */
42
51
  --cascivo-color-accent: oklch(0.65 0.2 250);
43
52
  --cascivo-color-accent-foreground: oklch(0.145 0.005 250);
44
- --cascivo-color-accent-hover: oklch(0.707 0.18 250);
45
- --cascivo-color-accent-active: oklch(0.808 0.14 250);
53
+ --cascivo-color-accent-hover: oklch(0.707 0.18 250); /* static fallback */
54
+ --cascivo-color-accent-hover: oklch(
55
+ from var(--cascivo-color-accent) 0.707 0.18 h
56
+ ); /* derived */
57
+ --cascivo-color-accent-active: oklch(0.808 0.14 250); /* static fallback */
58
+ --cascivo-color-accent-active: oklch(
59
+ from var(--cascivo-color-accent) 0.808 0.14 h
60
+ ); /* derived */
46
61
  --cascivo-color-accent-subtle: oklch(0.623 0.214 250 / 0.1);
47
62
  --cascivo-color-accent-muted: oklch(0.623 0.214 250 / 0.2);
48
63
 
49
64
  /* ── Destructive ──────────────────────────────────── */
50
65
  --cascivo-color-destructive: oklch(0.72 0.16 22);
51
- --cascivo-color-destructive-hover: oklch(0.628 0.188 22);
66
+ --cascivo-color-destructive-hover: oklch(0.628 0.188 22); /* static fallback */
67
+ --cascivo-color-destructive-hover: oklch(
68
+ from var(--cascivo-color-destructive) 0.628 0.188 h
69
+ ); /* derived */
52
70
  --cascivo-color-destructive-subtle: oklch(0.628 0.188 22 / 0.1);
53
71
 
54
72
  /* ── Semantic status colors ───────────────────────── */
@@ -63,6 +81,7 @@
63
81
  --cascivo-color-success-foreground: oklch(0.72 0.13 145);
64
82
  --cascivo-color-warning-foreground: oklch(0.82 0.13 75);
65
83
  --cascivo-color-destructive-foreground: oklch(0.85 0.12 22);
84
+ --cascivo-color-info-foreground: oklch(0.75 0.16 250);
66
85
 
67
86
  /* ── Primary — inverted monochrome ── */
68
87
  --cascivo-color-primary: oklch(0.922 0 0);
package/src/flat.css CHANGED
@@ -26,8 +26,8 @@
26
26
  /* ── Accent — vivid green ────────────────────────── */
27
27
  --cascivo-color-accent: oklch(0.5 0.2 145);
28
28
  --cascivo-color-accent-foreground: oklch(1 0 0);
29
- --cascivo-color-accent-hover: oklch(0.45 0.21 145);
30
-
29
+ --cascivo-color-accent-hover: oklch(0.45 0.21 145); /* static fallback */
30
+ --cascivo-color-accent-hover: oklch(from var(--cascivo-color-accent) 0.45 0.21 h); /* derived */
31
31
  /* ── Primary — accent-mapped ─────────────────────── */
32
32
  --cascivo-color-primary: var(--cascivo-color-accent);
33
33
  --cascivo-color-primary-fg: var(--cascivo-color-accent-foreground);
@@ -74,15 +74,29 @@
74
74
  --cascivo-color-text: var(--cascivo-color-foreground);
75
75
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
76
76
  --cascivo-color-text-muted: oklch(0.55 0 0);
77
- --cascivo-color-text-on-accent: oklch(1 0 0);
78
- --cascivo-color-text-on-destructive: oklch(1 0 0);
79
-
80
- --cascivo-color-accent-active: oklch(0.4 0.21 145);
77
+ --cascivo-color-text-on-accent: oklch(1 0 0); /* static fallback */
78
+ --cascivo-color-text-on-destructive: oklch(1 0 0); /* static fallback */
79
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
80
+ does not honor the static fallback on unsupported browsers — the var()
81
+ substitution keeps the invalid token and the color inherits foreground.
82
+ Guard the upgrade so only supporting browsers apply it. */
83
+ @supports (color: contrast-color(red)) {
84
+ & {
85
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
86
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
87
+ }
88
+ }
89
+ --cascivo-color-accent-active: oklch(0.4 0.21 145); /* static fallback */
90
+
91
+ --cascivo-color-accent-active: oklch(from var(--cascivo-color-accent) 0.4 0.21 h); /* derived */
81
92
  --cascivo-color-accent-subtle: oklch(0.95 0.04 145);
82
93
  --cascivo-color-accent-muted: oklch(0.9 0.07 145);
83
94
 
84
95
  --cascivo-color-destructive: oklch(0.52 0.2 22);
85
- --cascivo-color-destructive-hover: oklch(0.46 0.21 22);
96
+ --cascivo-color-destructive-hover: oklch(0.46 0.21 22); /* static fallback */
97
+ --cascivo-color-destructive-hover: oklch(
98
+ from var(--cascivo-color-destructive) 0.46 0.21 h
99
+ ); /* derived */
86
100
  --cascivo-color-destructive-subtle: oklch(0.95 0.04 22);
87
101
 
88
102
  --cascivo-color-success-subtle: oklch(0.95 0.04 145);
@@ -92,6 +106,7 @@
92
106
  --cascivo-color-success-foreground: oklch(0.52 0.18 145);
93
107
  --cascivo-color-warning-foreground: oklch(0.5 0.14 75);
94
108
  --cascivo-color-destructive-foreground: oklch(0.42 0.19 22);
109
+ --cascivo-color-info-foreground: oklch(0.45 0.19 250);
95
110
 
96
111
  --cascivo-radius-component: 0;
97
112
  --cascivo-radius-button: 0;
package/src/light.css CHANGED
@@ -32,19 +32,33 @@
32
32
 
33
33
  /* ── Text ─────────────────────────────────────────── */
34
34
  --cascivo-color-foreground: oklch(0.145 0.005 264);
35
- --cascivo-color-foreground-muted: oklch(0.554 0.018 264);
35
+ /* Darkened 0.5540.5 so muted text clears WCAG AA 4.5:1 on tinted surfaces
36
+ (surface-2, secondary), not just white. */
37
+ --cascivo-color-foreground-muted: oklch(0.5 0.018 264);
36
38
  --cascivo-color-text: var(--cascivo-color-foreground);
37
39
  --cascivo-color-text-subtle: var(--cascivo-gray-600);
38
- --cascivo-color-text-muted: var(--cascivo-gray-400);
39
- --cascivo-color-text-on-accent: oklch(1 0 0);
40
- --cascivo-color-text-on-destructive: oklch(1 0 0);
41
-
40
+ /* Was gray-400 (2.6:1 on white — fails). Darkened to clear 4.5:1 on every
41
+ light surface; drives hint/caption text across ~18 components. */
42
+ --cascivo-color-text-muted: oklch(0.5 0.016 264);
43
+ --cascivo-color-text-on-accent: oklch(1 0 0); /* static fallback */
44
+ --cascivo-color-text-on-destructive: oklch(1 0 0); /* static fallback */
45
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
46
+ does not honor the static fallback on unsupported browsers — the var()
47
+ substitution keeps the invalid token and the color inherits foreground.
48
+ Guard the upgrade so only supporting browsers apply it. */
49
+ @supports (color: contrast-color(red)) {
50
+ & {
51
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
52
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
53
+ }
54
+ }
42
55
  /* ── Accent (links, focus, info, active tint) ───────── */
43
56
  /* L lowered 0.623→0.52 so accent-as-link-text clears WCAG 2.2 AA 4.5:1 on
44
57
  white (was 3.55:1). Hover darkened to stay below the new base. */
45
58
  --cascivo-color-accent: oklch(0.52 0.2 250);
46
59
  --cascivo-color-accent-foreground: oklch(1 0 0);
47
- --cascivo-color-accent-hover: oklch(0.45 0.2 250);
60
+ --cascivo-color-accent-hover: oklch(0.45 0.2 250); /* static fallback */
61
+ --cascivo-color-accent-hover: oklch(from var(--cascivo-color-accent) 0.45 0.2 h); /* derived */
48
62
  --cascivo-color-accent-active: var(--cascivo-blue-800);
49
63
  --cascivo-color-accent-subtle: var(--cascivo-blue-50);
50
64
  --cascivo-color-accent-muted: var(--cascivo-blue-100);
@@ -73,6 +87,7 @@
73
87
  --cascivo-color-success-foreground: oklch(0.45 0.14 145);
74
88
  --cascivo-color-warning-foreground: oklch(0.5 0.14 75);
75
89
  --cascivo-color-destructive-foreground: oklch(0.448 0.17 22);
90
+ --cascivo-color-info-foreground: oklch(0.45 0.19 250); /* ≈6.5:1 on blue-50 */
76
91
 
77
92
  /* ── Radius — one knob; semantic scale derives in tokens ── */
78
93
  --cascivo-radius-base: 0.375rem; /* 6px */
@@ -111,7 +126,8 @@
111
126
  --cascivo-chart-7: oklch(0.62 0.12 350);
112
127
  --cascivo-chart-8: oklch(0.5 0.12 200);
113
128
  --cascivo-chart-grid: var(--cascivo-gray-200);
114
- --cascivo-chart-axis: var(--cascivo-gray-400);
129
+ /* Axis labels are text — gray-400 (2.6:1) fails; match text-muted. */
130
+ --cascivo-chart-axis: oklch(0.5 0.016 264);
115
131
 
116
132
  /* ── -content tokens (foreground ≥4.5:1 on paired background) ── */
117
133
  --cascivo-color-primary-content: var(--cascivo-color-primary-fg);
package/src/midnight.css CHANGED
@@ -34,14 +34,27 @@
34
34
  --cascivo-color-text: var(--cascivo-color-foreground);
35
35
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
36
36
  --cascivo-color-text-muted: oklch(0.52 0.02 280);
37
- --cascivo-color-text-on-accent: oklch(1 0 0);
38
- --cascivo-color-text-on-destructive: oklch(1 0 0);
39
-
37
+ --cascivo-color-text-on-accent: oklch(1 0 0); /* static fallback */
38
+ --cascivo-color-text-on-destructive: oklch(1 0 0); /* static fallback */
39
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
40
+ does not honor the static fallback on unsupported browsers — the var()
41
+ substitution keeps the invalid token and the color inherits foreground.
42
+ Guard the upgrade so only supporting browsers apply it. */
43
+ @supports (color: contrast-color(red)) {
44
+ & {
45
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
46
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
47
+ }
48
+ }
40
49
  /* ── Accent — violet ──────────────────────────────── */
41
50
  --cascivo-color-accent: oklch(0.7 0.22 290);
42
51
  --cascivo-color-accent-foreground: oklch(1 0 0);
43
- --cascivo-color-accent-hover: oklch(0.76 0.2 290);
44
- --cascivo-color-accent-active: oklch(0.82 0.17 290);
52
+ --cascivo-color-accent-hover: oklch(0.76 0.2 290); /* static fallback */
53
+ --cascivo-color-accent-hover: oklch(from var(--cascivo-color-accent) 0.76 0.2 h); /* derived */
54
+ --cascivo-color-accent-active: oklch(0.82 0.17 290); /* static fallback */
55
+ --cascivo-color-accent-active: oklch(
56
+ from var(--cascivo-color-accent) 0.82 0.17 h
57
+ ); /* derived */
45
58
  --cascivo-color-accent-subtle: oklch(0.7 0.22 290 / 0.12);
46
59
  --cascivo-color-accent-muted: oklch(0.7 0.22 290 / 0.22);
47
60
 
@@ -54,7 +67,10 @@
54
67
 
55
68
  /* ── Destructive ──────────────────────────────────── */
56
69
  --cascivo-color-destructive: oklch(0.72 0.16 22);
57
- --cascivo-color-destructive-hover: oklch(0.628 0.188 22);
70
+ --cascivo-color-destructive-hover: oklch(0.628 0.188 22); /* static fallback */
71
+ --cascivo-color-destructive-hover: oklch(
72
+ from var(--cascivo-color-destructive) 0.628 0.188 h
73
+ ); /* derived */
58
74
  --cascivo-color-destructive-subtle: oklch(0.628 0.188 22 / 0.1);
59
75
 
60
76
  /* ── Semantic status colors ───────────────────────── */
@@ -68,6 +84,7 @@
68
84
  --cascivo-color-success-foreground: oklch(0.72 0.13 145);
69
85
  --cascivo-color-warning-foreground: oklch(0.82 0.13 75);
70
86
  --cascivo-color-destructive-foreground: oklch(0.85 0.12 22);
87
+ --cascivo-color-info-foreground: oklch(0.78 0.16 290);
71
88
 
72
89
  /* ── Radius — 10px ───────────────────────────────── */
73
90
  --cascivo-radius-base: 0.625rem;
package/src/minimal.css CHANGED
@@ -26,8 +26,8 @@
26
26
  /* ── Accent — monochrome ─────────────────────────── */
27
27
  --cascivo-color-accent: oklch(0.25 0.01 80);
28
28
  --cascivo-color-accent-foreground: oklch(0.98 0.005 80);
29
- --cascivo-color-accent-hover: oklch(0.2 0.01 80);
30
-
29
+ --cascivo-color-accent-hover: oklch(0.2 0.01 80); /* static fallback */
30
+ --cascivo-color-accent-hover: oklch(from var(--cascivo-color-accent) 0.2 0.01 h); /* derived */
31
31
  /* ── Primary — accent-mapped ─────────────────────── */
32
32
  --cascivo-color-primary: var(--cascivo-color-accent);
33
33
  --cascivo-color-primary-fg: oklch(0.985 0 0);
@@ -74,15 +74,31 @@
74
74
  --cascivo-color-text: var(--cascivo-color-foreground);
75
75
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
76
76
  --cascivo-color-text-muted: oklch(0.65 0.012 80);
77
- --cascivo-color-text-on-accent: oklch(0.98 0.005 80);
78
- --cascivo-color-text-on-destructive: oklch(0.98 0.005 80);
79
-
80
- --cascivo-color-accent-active: oklch(0.32 0.01 80);
77
+ --cascivo-color-text-on-accent: oklch(0.98 0.005 80); /* static fallback */
78
+ --cascivo-color-text-on-destructive: oklch(0.98 0.005 80); /* static fallback */
79
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
80
+ does not honor the static fallback on unsupported browsers — the var()
81
+ substitution keeps the invalid token and the color inherits foreground.
82
+ Guard the upgrade so only supporting browsers apply it. */
83
+ @supports (color: contrast-color(red)) {
84
+ & {
85
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
86
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
87
+ }
88
+ }
89
+ --cascivo-color-accent-active: oklch(0.32 0.01 80); /* static fallback */
90
+
91
+ --cascivo-color-accent-active: oklch(
92
+ from var(--cascivo-color-accent) 0.32 0.01 h
93
+ ); /* derived */
81
94
  --cascivo-color-accent-subtle: oklch(0.94 0.008 80);
82
95
  --cascivo-color-accent-muted: oklch(0.9 0.01 80);
83
96
 
84
97
  --cascivo-color-destructive: oklch(0.55 0.14 22);
85
- --cascivo-color-destructive-hover: oklch(0.49 0.15 22);
98
+ --cascivo-color-destructive-hover: oklch(0.49 0.15 22); /* static fallback */
99
+ --cascivo-color-destructive-hover: oklch(
100
+ from var(--cascivo-color-destructive) 0.49 0.15 h
101
+ ); /* derived */
86
102
  --cascivo-color-destructive-subtle: oklch(0.96 0.025 22);
87
103
 
88
104
  --cascivo-color-success-subtle: oklch(0.96 0.03 145);
@@ -92,6 +108,7 @@
92
108
  --cascivo-color-success-foreground: oklch(0.45 0.13 145);
93
109
  --cascivo-color-warning-foreground: oklch(0.5 0.12 75);
94
110
  --cascivo-color-destructive-foreground: oklch(0.448 0.17 22);
111
+ --cascivo-color-info-foreground: oklch(0.45 0.16 250);
95
112
 
96
113
  --cascivo-radius-component: var(--cascivo-radius-base);
97
114
  --cascivo-radius-button: var(--cascivo-radius-base);
package/src/pastel.css CHANGED
@@ -34,14 +34,25 @@
34
34
  --cascivo-color-text: var(--cascivo-color-foreground);
35
35
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
36
36
  --cascivo-color-text-muted: oklch(0.7 0.02 325);
37
- --cascivo-color-text-on-accent: oklch(1 0 0);
38
- --cascivo-color-text-on-destructive: oklch(1 0 0);
39
-
37
+ --cascivo-color-text-on-accent: oklch(1 0 0); /* static fallback */
38
+ --cascivo-color-text-on-destructive: oklch(1 0 0); /* static fallback */
39
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
40
+ does not honor the static fallback on unsupported browsers — the var()
41
+ substitution keeps the invalid token and the color inherits foreground.
42
+ Guard the upgrade so only supporting browsers apply it. */
43
+ @supports (color: contrast-color(red)) {
44
+ & {
45
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
46
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
47
+ }
48
+ }
40
49
  /* ── Accent — candy pink ──────────────────────────── */
41
50
  --cascivo-color-accent: oklch(0.68 0.18 350);
42
51
  --cascivo-color-accent-foreground: oklch(1 0 0);
43
- --cascivo-color-accent-hover: oklch(0.62 0.19 350);
44
- --cascivo-color-accent-active: oklch(0.56 0.2 350);
52
+ --cascivo-color-accent-hover: oklch(0.62 0.19 350); /* static fallback */
53
+ --cascivo-color-accent-hover: oklch(from var(--cascivo-color-accent) 0.62 0.19 h); /* derived */
54
+ --cascivo-color-accent-active: oklch(0.56 0.2 350); /* static fallback */
55
+ --cascivo-color-accent-active: oklch(from var(--cascivo-color-accent) 0.56 0.2 h); /* derived */
45
56
  --cascivo-color-accent-subtle: oklch(0.96 0.04 350);
46
57
  --cascivo-color-accent-muted: oklch(0.93 0.07 350);
47
58
 
@@ -54,7 +65,10 @@
54
65
 
55
66
  /* ── Destructive ──────────────────────────────────── */
56
67
  --cascivo-color-destructive: oklch(0.58 0.18 22);
57
- --cascivo-color-destructive-hover: oklch(0.52 0.19 22);
68
+ --cascivo-color-destructive-hover: oklch(0.52 0.19 22); /* static fallback */
69
+ --cascivo-color-destructive-hover: oklch(
70
+ from var(--cascivo-color-destructive) 0.52 0.19 h
71
+ ); /* derived */
58
72
  --cascivo-color-destructive-subtle: oklch(0.96 0.04 22);
59
73
 
60
74
  /* ── Semantic status colors ───────────────────────── */
@@ -68,6 +82,7 @@
68
82
  --cascivo-color-success-foreground: oklch(0.46 0.13 165);
69
83
  --cascivo-color-warning-foreground: oklch(0.5 0.13 75);
70
84
  --cascivo-color-destructive-foreground: oklch(0.448 0.17 22);
85
+ --cascivo-color-info-foreground: oklch(0.5 0.16 350);
71
86
 
72
87
  /* ── Radius — 16px pill ──────────────────────────── */
73
88
  --cascivo-radius-base: 1rem;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Opt-in Tailwind v4 interop bridge for cascivo.
3
+ *
4
+ * Import this LAST, after your Tailwind entry and your cascivo theme imports,
5
+ * from a stylesheet processed by Tailwind v4:
6
+ *
7
+ * @import 'tailwindcss';
8
+ * @import '@cascivo/tokens';
9
+ * @import '@cascivo/themes/light.css';
10
+ * @import '@cascivo/themes/dark.css';
11
+ * @import '@cascivo/themes/tailwind.css'; // this file — last
12
+ *
13
+ * It does two things and changes neither token system:
14
+ * 1. Re-points Tailwind's `dark:` variant at cascivo's `[data-theme="dark"]`
15
+ * mechanism, so a single attribute drives BOTH systems (no `.dark` class
16
+ * needed, no attribute-setting from CSS, no duplicated token values).
17
+ * 2. Bridges cascivo semantic color tokens into Tailwind's `--color-*`
18
+ * namespace, so utilities like `bg-accent`, `text-foreground`, and
19
+ * `border-border` resolve to cascivo values.
20
+ *
21
+ * Outside a Tailwind v4 build these are unknown at-rules and are simply ignored,
22
+ * so importing this file in a non-Tailwind project is harmless.
23
+ *
24
+ * See docs/USING-WITH-TAILWIND.md for the full setup and dark-mode guidance.
25
+ */
26
+
27
+ /* 1 — Tailwind's dark: variant follows cascivo's [data-theme] attribute. */
28
+ @custom-variant dark (&:where([data-theme='dark'], [data-theme='dark'] *));
29
+
30
+ /* 2 — cascivo semantic tokens → Tailwind --color-* utilities. `inline` so the
31
+ values are read at use-site, keeping them reactive to the active theme. */
32
+ @theme inline {
33
+ --color-background: var(--cascivo-color-background);
34
+ --color-foreground: var(--cascivo-color-foreground);
35
+ --color-surface: var(--cascivo-color-surface);
36
+ --color-surface-raised: var(--cascivo-color-surface-raised);
37
+ --color-border: var(--cascivo-color-border);
38
+ --color-muted: var(--cascivo-color-text-muted);
39
+ --color-subtle: var(--cascivo-color-text-subtle);
40
+
41
+ --color-accent: var(--cascivo-color-accent);
42
+ --color-accent-foreground: var(--cascivo-color-accent-foreground);
43
+ --color-primary: var(--cascivo-color-primary);
44
+ --color-secondary: var(--cascivo-color-secondary);
45
+
46
+ --color-destructive: var(--cascivo-color-destructive);
47
+ --color-success: var(--cascivo-color-success);
48
+ --color-warning: var(--cascivo-color-warning);
49
+ --color-info: var(--cascivo-color-info);
50
+ }
package/src/terminal.css CHANGED
@@ -34,14 +34,27 @@
34
34
  --cascivo-color-text: var(--cascivo-color-foreground);
35
35
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
36
36
  --cascivo-color-text-muted: oklch(0.48 0.04 148);
37
- --cascivo-color-text-on-accent: oklch(0.17 0.01 150);
38
- --cascivo-color-text-on-destructive: oklch(0.17 0.01 150);
39
-
37
+ --cascivo-color-text-on-accent: oklch(0.17 0.01 150); /* static fallback */
38
+ --cascivo-color-text-on-destructive: oklch(0.17 0.01 150); /* static fallback */
39
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
40
+ does not honor the static fallback on unsupported browsers — the var()
41
+ substitution keeps the invalid token and the color inherits foreground.
42
+ Guard the upgrade so only supporting browsers apply it. */
43
+ @supports (color: contrast-color(red)) {
44
+ & {
45
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
46
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
47
+ }
48
+ }
40
49
  /* ── Accent — bright phosphor green ──────────────── */
41
50
  --cascivo-color-accent: oklch(0.82 0.2 145);
42
51
  --cascivo-color-accent-foreground: oklch(0.17 0.01 150);
43
- --cascivo-color-accent-hover: oklch(0.88 0.18 145);
44
- --cascivo-color-accent-active: oklch(0.92 0.15 145);
52
+ --cascivo-color-accent-hover: oklch(0.88 0.18 145); /* static fallback */
53
+ --cascivo-color-accent-hover: oklch(from var(--cascivo-color-accent) 0.88 0.18 h); /* derived */
54
+ --cascivo-color-accent-active: oklch(0.92 0.15 145); /* static fallback */
55
+ --cascivo-color-accent-active: oklch(
56
+ from var(--cascivo-color-accent) 0.92 0.15 h
57
+ ); /* derived */
45
58
  --cascivo-color-accent-subtle: oklch(0.82 0.2 145 / 0.1);
46
59
  --cascivo-color-accent-muted: oklch(0.82 0.2 145 / 0.2);
47
60
 
@@ -54,7 +67,10 @@
54
67
 
55
68
  /* ── Destructive — red on dark green bg ───────────── */
56
69
  --cascivo-color-destructive: oklch(0.72 0.16 22);
57
- --cascivo-color-destructive-hover: oklch(0.78 0.14 22);
70
+ --cascivo-color-destructive-hover: oklch(0.78 0.14 22); /* static fallback */
71
+ --cascivo-color-destructive-hover: oklch(
72
+ from var(--cascivo-color-destructive) 0.78 0.14 h
73
+ ); /* derived */
58
74
  --cascivo-color-destructive-subtle: oklch(0.72 0.16 22 / 0.1);
59
75
 
60
76
  /* ── Semantic status colors ───────────────────────── */
@@ -68,6 +84,7 @@
68
84
  --cascivo-color-success-foreground: oklch(0.82 0.2 145);
69
85
  --cascivo-color-warning-foreground: oklch(0.82 0.16 75);
70
86
  --cascivo-color-destructive-foreground: oklch(0.82 0.15 22);
87
+ --cascivo-color-info-foreground: oklch(0.82 0.2 145);
71
88
 
72
89
  /* ── Radius — zero ───────────────────────────────── */
73
90
  --cascivo-radius-base: 0;
package/src/warm.css CHANGED
@@ -34,9 +34,18 @@
34
34
  --cascivo-color-text: var(--cascivo-color-foreground);
35
35
  --cascivo-color-text-subtle: var(--cascivo-color-foreground-muted);
36
36
  --cascivo-color-text-muted: oklch(0.64 0.025 65);
37
- --cascivo-color-text-on-accent: oklch(0.18 0.015 50);
38
- --cascivo-color-text-on-destructive: oklch(1 0 0);
39
-
37
+ --cascivo-color-text-on-accent: oklch(0.18 0.015 50); /* static fallback */
38
+ --cascivo-color-text-on-destructive: oklch(1 0 0); /* static fallback */
39
+ /* Progressive auto-contrast: contrast-color() stored in a custom property
40
+ does not honor the static fallback on unsupported browsers — the var()
41
+ substitution keeps the invalid token and the color inherits foreground.
42
+ Guard the upgrade so only supporting browsers apply it. */
43
+ @supports (color: contrast-color(red)) {
44
+ & {
45
+ --cascivo-color-text-on-accent: contrast-color(var(--cascivo-color-accent));
46
+ --cascivo-color-text-on-destructive: contrast-color(var(--cascivo-color-destructive));
47
+ }
48
+ }
40
49
  /* ── Accent ───────────────────────────────────────── */
41
50
  --cascivo-color-accent: oklch(0.768 0.145 75);
42
51
  --cascivo-color-accent-foreground: oklch(0.18 0.015 50);
@@ -68,6 +77,7 @@
68
77
  --cascivo-color-success-foreground: oklch(0.45 0.14 145);
69
78
  --cascivo-color-warning-foreground: oklch(0.5 0.14 75);
70
79
  --cascivo-color-destructive-foreground: oklch(0.448 0.17 22);
80
+ --cascivo-color-info-foreground: oklch(0.45 0.19 250);
71
81
 
72
82
  /* ── Radius — one knob, warmer = rounder (8px) ────── */
73
83
  --cascivo-radius-base: 0.5rem;