@tailor-platform/app-shell 1.16.0 → 1.17.0

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.
Files changed (42) hide show
  1. package/dist/app-shell-core.css +1 -1
  2. package/dist/app-shell.d.ts +692 -106
  3. package/dist/app-shell.js +6294 -4939
  4. package/dist/{appshell-B0wh5Lq0.js → appshell-CahhZy7v.js} +316 -297
  5. package/dist/semantic-contrast.test.ts +154 -0
  6. package/dist/style-entry.d.ts +117 -82
  7. package/dist/testing.d.ts +122 -85
  8. package/dist/testing.js +1 -1
  9. package/dist/theme-bridge.test.ts +101 -1
  10. package/dist/theme.bridge.css +91 -0
  11. package/dist/theme.css +6 -1
  12. package/dist/themes/_template.css +7 -1
  13. package/dist/themes/bloom.css +0 -6
  14. package/dist/themes/cream.css +0 -6
  15. package/dist/themes/default.css +389 -69
  16. package/dist/vite-plugin.d.ts +117 -82
  17. package/package.json +1 -1
  18. package/skills/app-shell-patterns/SKILL.md +7 -5
  19. package/skills/app-shell-patterns/references/api/define-module.md +2 -2
  20. package/skills/app-shell-patterns/references/api/define-resource.md +2 -2
  21. package/skills/app-shell-patterns/references/api/use-app-shell-config.md +53 -47
  22. package/skills/app-shell-patterns/references/api/use-app-shell-data.md +30 -26
  23. package/skills/app-shell-patterns/references/api/use-app-shell.md +37 -30
  24. package/skills/app-shell-patterns/references/api/use-toast.md +28 -31
  25. package/skills/app-shell-patterns/references/components/app-shell.md +4 -4
  26. package/skills/app-shell-patterns/references/components/card.md +79 -7
  27. package/skills/app-shell-patterns/references/components/data-table.md +267 -52
  28. package/skills/app-shell-patterns/references/components/date-picker.md +32 -21
  29. package/skills/app-shell-patterns/references/components/filter-rail.md +165 -0
  30. package/skills/app-shell-patterns/references/components/sidebar-group.md +6 -0
  31. package/skills/app-shell-patterns/references/components/sidebar-section.md +114 -0
  32. package/skills/app-shell-patterns/references/concepts/custom-components.md +1 -1
  33. package/skills/app-shell-patterns/references/concepts/file-based-routing.md +7 -1
  34. package/skills/app-shell-patterns/references/concepts/graphql.md +20 -14
  35. package/skills/app-shell-patterns/references/concepts/routing-navigation.md +41 -3
  36. package/skills/app-shell-patterns/references/concepts/sidebar-navigation.md +32 -0
  37. package/skills/app-shell-patterns/references/concepts/styling-theming.md +255 -58
  38. package/skills/app-shell-patterns/references/migrations.md +21 -0
  39. package/skills/app-shell-patterns/references/pages/document-detail.md +6 -6
  40. package/skills/app-shell-patterns/references/patterns/form-modal.md +26 -20
  41. package/skills/app-shell-patterns/references/patterns/interaction-multi-select.md +129 -118
  42. package/skills/app-shell-patterns/references/patterns/list-dense-scan.md +2 -2
@@ -36,6 +36,56 @@
36
36
  sans-serif
37
37
  );
38
38
 
39
+ /*
40
+ * Typography roles. `text-heading-lg` sets font-size, line-height, font-weight and
41
+ * letter-spacing together. The values live in themes/default.css and are referenced
42
+ * with `var()` here, like the colors: `@theme inline` writes literals into the
43
+ * utility, so a value placed here could not be overridden on `:root`.
44
+ *
45
+ * The `--text-*` namespace cannot set font-family. `text-code-sm` is used with
46
+ * `font-mono`.
47
+ */
48
+ --text-heading-lg: var(--app-shell-type-heading-lg-size);
49
+ --text-heading-lg--line-height: var(--app-shell-type-heading-lg-line-height);
50
+ --text-heading-lg--font-weight: var(--app-shell-type-heading-lg-weight);
51
+ --text-heading-lg--letter-spacing: var(--app-shell-type-heading-lg-letter-spacing);
52
+ --text-heading-md: var(--app-shell-type-heading-md-size);
53
+ --text-heading-md--line-height: var(--app-shell-type-heading-md-line-height);
54
+ --text-heading-md--font-weight: var(--app-shell-type-heading-md-weight);
55
+ --text-heading-md--letter-spacing: var(--app-shell-type-heading-md-letter-spacing);
56
+ --text-heading-sm: var(--app-shell-type-heading-sm-size);
57
+ --text-heading-sm--line-height: var(--app-shell-type-heading-sm-line-height);
58
+ --text-heading-sm--font-weight: var(--app-shell-type-heading-sm-weight);
59
+ --text-heading-sm--letter-spacing: var(--app-shell-type-heading-sm-letter-spacing);
60
+ --text-body-md: var(--app-shell-type-body-md-size);
61
+ --text-body-md--line-height: var(--app-shell-type-body-md-line-height);
62
+ --text-body-md--font-weight: var(--app-shell-type-body-md-weight);
63
+ --text-body-md--letter-spacing: var(--app-shell-type-body-md-letter-spacing);
64
+ --text-body-sm: var(--app-shell-type-body-sm-size);
65
+ --text-body-sm--line-height: var(--app-shell-type-body-sm-line-height);
66
+ --text-body-sm--font-weight: var(--app-shell-type-body-sm-weight);
67
+ --text-body-sm--letter-spacing: var(--app-shell-type-body-sm-letter-spacing);
68
+ --text-label-md: var(--app-shell-type-label-md-size);
69
+ --text-label-md--line-height: var(--app-shell-type-label-md-line-height);
70
+ --text-label-md--font-weight: var(--app-shell-type-label-md-weight);
71
+ --text-label-md--letter-spacing: var(--app-shell-type-label-md-letter-spacing);
72
+ --text-label-sm: var(--app-shell-type-label-sm-size);
73
+ --text-label-sm--line-height: var(--app-shell-type-label-sm-line-height);
74
+ --text-label-sm--font-weight: var(--app-shell-type-label-sm-weight);
75
+ --text-label-sm--letter-spacing: var(--app-shell-type-label-sm-letter-spacing);
76
+ --text-code-sm: var(--app-shell-type-code-sm-size);
77
+ --text-code-sm--line-height: var(--app-shell-type-code-sm-line-height);
78
+ --text-code-sm--font-weight: var(--app-shell-type-code-sm-weight);
79
+ --text-code-sm--letter-spacing: var(--app-shell-type-code-sm-letter-spacing);
80
+ --text-body-md-relaxed: var(--app-shell-type-body-md-relaxed-size);
81
+ --text-body-md-relaxed--line-height: var(--app-shell-type-body-md-relaxed-line-height);
82
+ --text-body-md-relaxed--font-weight: var(--app-shell-type-body-md-relaxed-weight);
83
+ --text-body-md-relaxed--letter-spacing: var(--app-shell-type-body-md-relaxed-letter-spacing);
84
+ --text-body-sm-relaxed: var(--app-shell-type-body-sm-relaxed-size);
85
+ --text-body-sm-relaxed--line-height: var(--app-shell-type-body-sm-relaxed-line-height);
86
+ --text-body-sm-relaxed--font-weight: var(--app-shell-type-body-sm-relaxed-weight);
87
+ --text-body-sm-relaxed--letter-spacing: var(--app-shell-type-body-sm-relaxed-letter-spacing);
88
+
39
89
  --color-background: var(--background);
40
90
  --color-foreground: var(--foreground);
41
91
  --color-card: var(--card);
@@ -100,6 +150,47 @@
100
150
  --color-alert-info-foreground-muted: var(--alert-info-foreground-muted);
101
151
  --color-alert-info-border: var(--alert-info-border);
102
152
 
153
+ --color-neutral-surface: var(--neutral-surface);
154
+ --color-neutral-surface-hover: var(--neutral-surface-hover);
155
+ --color-neutral-border: var(--neutral-border);
156
+ --color-neutral-solid: var(--neutral-solid);
157
+ --color-neutral-solid-hover: var(--neutral-solid-hover);
158
+ --color-neutral-text: var(--neutral-text);
159
+ --color-neutral-contrast: var(--neutral-contrast);
160
+ --color-neutral-indicator: var(--neutral-indicator);
161
+ --color-info-surface: var(--info-surface);
162
+ --color-info-surface-hover: var(--info-surface-hover);
163
+ --color-info-border: var(--info-border);
164
+ --color-info-solid: var(--info-solid);
165
+ --color-info-solid-hover: var(--info-solid-hover);
166
+ --color-info-text: var(--info-text);
167
+ --color-info-contrast: var(--info-contrast);
168
+ --color-info-indicator: var(--info-indicator);
169
+ --color-success-surface: var(--success-surface);
170
+ --color-success-surface-hover: var(--success-surface-hover);
171
+ --color-success-border: var(--success-border);
172
+ --color-success-solid: var(--success-solid);
173
+ --color-success-solid-hover: var(--success-solid-hover);
174
+ --color-success-text: var(--success-text);
175
+ --color-success-contrast: var(--success-contrast);
176
+ --color-success-indicator: var(--success-indicator);
177
+ --color-warning-surface: var(--warning-surface);
178
+ --color-warning-surface-hover: var(--warning-surface-hover);
179
+ --color-warning-border: var(--warning-border);
180
+ --color-warning-solid: var(--warning-solid);
181
+ --color-warning-solid-hover: var(--warning-solid-hover);
182
+ --color-warning-text: var(--warning-text);
183
+ --color-warning-contrast: var(--warning-contrast);
184
+ --color-warning-indicator: var(--warning-indicator);
185
+ --color-danger-surface: var(--danger-surface);
186
+ --color-danger-surface-hover: var(--danger-surface-hover);
187
+ --color-danger-border: var(--danger-border);
188
+ --color-danger-solid: var(--danger-solid);
189
+ --color-danger-solid-hover: var(--danger-solid-hover);
190
+ --color-danger-text: var(--danger-text);
191
+ --color-danger-contrast: var(--danger-contrast);
192
+ --color-danger-indicator: var(--danger-indicator);
193
+
103
194
  --shadow-xs: var(--semantic-shadow-xs);
104
195
  --shadow-sm: var(--semantic-shadow-sm);
105
196
  --shadow-md: var(--semantic-shadow-md);
package/dist/theme.css CHANGED
@@ -16,7 +16,12 @@
16
16
  * 4. PALETTE — optional: radius, charts, shadows, destructive.
17
17
  *
18
18
  * Inherited from default.css — do not duplicate in new palettes:
19
- * --ring, --sidebar-*, --status-*, --alert-*.
19
+ * --ring, --sidebar-*, --primitive-* (colour scales), --status-*, --alert-*,
20
+ * --app-shell-type-* (typography roles).
21
+ * The colour roles --{intent}-{role} inherit too; a palette overrides them
22
+ * only to recolour the status components. Typography roles are inherited
23
+ * the same way: do not copy the defaults, override only the variables
24
+ * whose values differ.
20
25
  *
21
26
  * Light/dark mode is controlled separately via `.dark` on <html>.
22
27
  * Palette selection is by CSS import; there is no runtime palette prop.
@@ -17,7 +17,13 @@
17
17
  * `@tailor-platform/app-shell/styles` in the consuming app.
18
18
  *
19
19
  * DO NOT SET (inherited from `:root` in default.css):
20
- * --ring, --sidebar-*, --status-*, --alert-*
20
+ * --ring, --sidebar-*, --primitive-* (colour scales), --status-*, --alert-*,
21
+ * --app-shell-type-*
22
+ * The colour roles --{info|success|warning|danger|neutral}-{role} also inherit.
23
+ * Override a role only to recolour the status components (Badge, Alert, ...)
24
+ * for this palette; never set --status-* or --alert-*, they alias the roles.
25
+ * Typography roles (--app-shell-type-*) inherit too: do not copy the defaults,
26
+ * override only the variables whose values differ.
21
27
  *
22
28
  * PREVIEW: `/showcase/colors` in the Vite example app.
23
29
  * ═══════════════════════════════════════════════════════════════════════════
@@ -146,15 +146,9 @@ html
146
146
  background-color: transparent;
147
147
  }
148
148
 
149
- html [data-slot="button"][class*="astw:bg-background"][class*="astw:border"],
150
149
  html [data-slot="data-table-filter-chip"] {
151
150
  background-color: transparent;
152
151
  transition:
153
152
  background-color 0.12s ease,
154
153
  color 0.12s ease;
155
154
  }
156
-
157
- html [data-slot="button"][class*="astw:bg-background"][class*="astw:border"]:hover:not(:disabled) {
158
- background-color: var(--accent);
159
- color: var(--accent-foreground);
160
- }
@@ -146,15 +146,9 @@ html
146
146
  background-color: transparent;
147
147
  }
148
148
 
149
- html [data-slot="button"][class*="astw:bg-background"][class*="astw:border"],
150
149
  html [data-slot="data-table-filter-chip"] {
151
150
  background-color: transparent;
152
151
  transition:
153
152
  background-color 0.12s ease,
154
153
  color 0.12s ease;
155
154
  }
156
-
157
- html [data-slot="button"][class*="astw:bg-background"][class*="astw:border"]:hover:not(:disabled) {
158
- background-color: var(--accent);
159
- color: var(--accent-foreground);
160
- }
@@ -27,15 +27,15 @@
27
27
 
28
28
  /* ── 4. SYSTEM ────────────────────────────────────────────────────────── */
29
29
  --background: rgba(250, 250, 250, 1);
30
- --foreground: rgba(10, 10, 10, 1);
30
+ --foreground: var(--primitive-gray-950);
31
31
  --card: rgba(255, 255, 255, 1);
32
32
  --card-foreground: rgba(10, 10, 10, 1);
33
33
  --popover: rgba(255, 255, 255, 1);
34
34
  --popover-foreground: rgba(10, 10, 10, 1);
35
35
  --muted: rgba(245, 245, 245, 1);
36
- --muted-foreground: rgba(115, 115, 115, 1);
37
- --border: rgba(229, 229, 229, 1);
38
- --input: rgba(229, 229, 229, 1);
36
+ --muted-foreground: var(--primitive-gray-500);
37
+ --border: var(--primitive-gray-200);
38
+ --input: var(--primitive-gray-200);
39
39
  --sidebar: rgba(250, 250, 250, 1);
40
40
  --sidebar-foreground: rgba(10, 10, 10, 1);
41
41
  --sidebar-border: rgba(229, 229, 229, 1);
@@ -53,51 +53,13 @@
53
53
  --semantic-shadow-sm: 0 1px 3px 0 rgb(15 23 42 / 0.08), 0 1px 2px -1px rgb(15 23 42 / 0.08);
54
54
  --semantic-shadow-md: 0 4px 6px -1px rgb(15 23 42 / 0.09), 0 2px 4px -2px rgb(15 23 42 / 0.06);
55
55
  --semantic-shadow-lg: 0 10px 15px -3px rgb(15 23 42 / 0.12), 0 4px 6px -4px rgb(15 23 42 / 0.09);
56
-
57
- /* ── 6. SEMANTIC — product-wide; inherited by all palettes, do not override */
58
- --status-default: #737373;
59
- --status-neutral: #0ea5e9;
60
- --status-completed: #22c55e;
61
- --status-attention: #f59e0b;
62
- --status-danger: #ef4444;
63
- --alert-neutral-background: var(--muted);
64
- --alert-neutral-foreground: var(--foreground);
65
- --alert-neutral-foreground-muted: var(--muted-foreground);
66
- --alert-neutral-border: var(--border);
67
- --alert-success-foreground: #15803d;
68
- --alert-success-foreground-muted: color-mix(
69
- in srgb,
70
- var(--alert-success-foreground) 80%,
71
- transparent
72
- );
73
- --alert-success-background: color-mix(in srgb, #22c55e 10%, transparent);
74
- --alert-success-border: color-mix(in srgb, #22c55e 20%, transparent);
75
- --alert-warning-foreground: #a16207;
76
- --alert-warning-foreground-muted: color-mix(
77
- in srgb,
78
- var(--alert-warning-foreground) 80%,
79
- transparent
80
- );
81
- --alert-warning-background: color-mix(in srgb, #eab308 10%, transparent);
82
- --alert-warning-border: color-mix(in srgb, #eab308 20%, transparent);
83
- --alert-error-foreground: var(--destructive);
84
- --alert-error-foreground-muted: color-mix(
85
- in srgb,
86
- var(--alert-error-foreground) 80%,
87
- transparent
88
- );
89
- --alert-error-background: color-mix(in srgb, var(--destructive) 10%, transparent);
90
- --alert-error-border: color-mix(in srgb, var(--destructive) 20%, transparent);
91
- --alert-info-foreground: #1d4ed8;
92
- --alert-info-foreground-muted: color-mix(in srgb, var(--alert-info-foreground) 80%, transparent);
93
- --alert-info-background: color-mix(in srgb, #3b82f6 10%, transparent);
94
- --alert-info-border: color-mix(in srgb, #3b82f6 20%, transparent);
95
56
  }
96
57
 
97
58
  /*
98
- * Dark variant. Overrides BRAND + SYSTEM (+ semantic foregrounds that differ).
99
- * Shared aliases/ring re-resolve when BRAND changes; `--radius` and `--status-*`
100
- * inherit from the light block.
59
+ * Dark variant. Overrides BRAND + SYSTEM + PALETTE. The primitive scales (6),
60
+ * the semantic roles (7) and the typography roles (8) follow below. Shared
61
+ * aliases/ring re-resolve when BRAND changes; `--radius` inherits from the
62
+ * light block.
101
63
  */
102
64
  .dark {
103
65
  color-scheme: dark;
@@ -112,13 +74,13 @@
112
74
 
113
75
  /* ── 4. SYSTEM (dark) ─────────────────────────────────────────────────── */
114
76
  --background: rgba(10, 10, 10, 1);
115
- --foreground: rgba(250, 250, 250, 1);
77
+ --foreground: var(--primitive-gray-50);
116
78
  --card: rgba(23, 23, 23, 1);
117
79
  --card-foreground: rgba(250, 250, 250, 1);
118
80
  --popover: rgba(38, 38, 38, 1);
119
81
  --popover-foreground: rgba(250, 250, 250, 1);
120
82
  --muted: rgba(38, 38, 38, 1);
121
- --muted-foreground: rgba(163, 163, 163, 1);
83
+ --muted-foreground: var(--primitive-gray-400);
122
84
  --border: rgba(255, 255, 255, 0.1);
123
85
  --input: rgba(255, 255, 255, 0.15);
124
86
  --sidebar: rgba(10, 10, 10, 1);
@@ -137,26 +99,384 @@
137
99
  --semantic-shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.38), 0 1px 2px -1px rgb(0 0 0 / 0.32);
138
100
  --semantic-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.35), 0 2px 4px -2px rgb(0 0 0 / 0.28);
139
101
  --semantic-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.42), 0 4px 6px -4px rgb(0 0 0 / 0.35);
102
+ }
103
+
104
+ /*
105
+ * 6. PRIMITIVE SCALES — internal; consumers use the semantic roles (7) below.
106
+ *
107
+ * One gray scale and four Radix-style 12-step + alpha hue scales, light then
108
+ * dark. Names are prefixed to avoid colliding with a consumer's own copy of
109
+ * Radix Colors. Not bridged to Tailwind. See decisions/semantic-color-roles.md
110
+ * for how they were made. The hue "alpha" steps are translucent only where the
111
+ * generator could express them; some light steps (for example amber a2-a6)
112
+ * resolve to opaque hex.
113
+ *
114
+ * Gray is the Tailwind `neutral` family (the values this palette already used)
115
+ * and is the same in both modes, so it is declared once; the SYSTEM text and
116
+ * line tokens (4) read it. Surfaces stay literal: they are theme inputs.
117
+ */
118
+ :root {
119
+ /* gray — both modes */
120
+ --primitive-gray-50: #fafafa;
121
+ --primitive-gray-100: #f5f5f5;
122
+ --primitive-gray-200: #e5e5e5;
123
+ --primitive-gray-300: #d4d4d4;
124
+ --primitive-gray-400: #a3a3a3;
125
+ --primitive-gray-500: #737373;
126
+ --primitive-gray-600: #525252;
127
+ --primitive-gray-700: #404040;
128
+ --primitive-gray-800: #262626;
129
+ --primitive-gray-900: #171717;
130
+ --primitive-gray-950: #0a0a0a;
131
+
132
+ /* hues — light */
133
+ --primitive-blue-1: #f7f8f9;
134
+ --primitive-blue-2: #f0f4fa;
135
+ --primitive-blue-3: #e5ecf9;
136
+ --primitive-blue-4: #d6e4fd;
137
+ --primitive-blue-5: #c5d9ff;
138
+ --primitive-blue-6: #b0cbff;
139
+ --primitive-blue-7: #98b9f7;
140
+ --primitive-blue-8: #769ff0;
141
+ --primitive-blue-9: #2563eb;
142
+ --primitive-blue-10: #2057d1;
143
+ --primitive-blue-11: #1e55cf;
144
+ --primitive-blue-12: #152e63;
145
+ --primitive-blue-a1: #3b7bbb04;
146
+ --primitive-blue-a2: #136ffa0b;
147
+ --primitive-blue-a3: #0758ef16;
148
+ --primitive-blue-a4: #bed6ff99;
149
+ --primitive-blue-a5: #c5d9ff;
150
+ --primitive-blue-a6: #b0cbff;
151
+ --primitive-blue-a7: #0155f364;
152
+ --primitive-blue-a8: #004ee787;
153
+ --primitive-blue-a9: #014ae9da;
154
+ --primitive-blue-a10: #0140ccdf;
155
+ --primitive-blue-a11: #013fcae1;
156
+ --primitive-blue-a12: #001b55ea;
157
+ --primitive-blue-contrast: #ffffff;
158
+
159
+ --primitive-green-1: #f5f9f6;
160
+ --primitive-green-2: #eff5f0;
161
+ --primitive-green-3: #e1f1e3;
162
+ --primitive-green-4: #d1ead5;
163
+ --primitive-green-5: #bfe2c5;
164
+ --primitive-green-6: #a7d7b0;
165
+ --primitive-green-7: #88c895;
166
+ --primitive-green-8: #57b36f;
167
+ --primitive-green-9: #15803d;
168
+ --primitive-green-10: #00722f;
169
+ --primitive-green-11: #047936;
170
+ --primitive-green-12: #1e3c25;
171
+ --primitive-green-a1: #26d05006;
172
+ --primitive-green-a2: #1190260c;
173
+ --primitive-green-a3: #04a1181a;
174
+ --primitive-green-a4: #02991a2a;
175
+ --primitive-green-a5: #04961d3d;
176
+ --primitive-green-a6: #01911c55;
177
+ --primitive-green-a7: #028e1e75;
178
+ --primitive-green-a8: #028e26a7;
179
+ --primitive-green-a9: #00752cea;
180
+ --primitive-green-a10: #00722f;
181
+ --primitive-green-a11: #007733fb;
182
+ --primitive-green-a12: #012309e1;
183
+ --primitive-green-contrast: #ffffff;
184
+
185
+ --primitive-amber-1: #f9f7f5;
186
+ --primitive-amber-2: #fff2e1;
187
+ --primitive-amber-3: #ffe7bd;
188
+ --primitive-amber-4: #ffdca5;
189
+ --primitive-amber-5: #ffd089;
190
+ --primitive-amber-6: #ffbe5d;
191
+ --primitive-amber-7: #f8ad4a;
192
+ --primitive-amber-8: #e99300;
193
+ --primitive-amber-9: #f59e0b;
194
+ --primitive-amber-10: #e99300;
195
+ --primitive-amber-11: #a35f00;
196
+ --primitive-amber-12: #4f3515;
197
+ --primitive-amber-a1: #d07b2606;
198
+ --primitive-amber-a2: #fff2e1;
199
+ --primitive-amber-a3: #ffe7bd;
200
+ --primitive-amber-a4: #ffdca5;
201
+ --primitive-amber-a5: #ffd089;
202
+ --primitive-amber-a6: #ffbe5d;
203
+ --primitive-amber-a7: #f78c00b4;
204
+ --primitive-amber-a8: #e99300;
205
+ --primitive-amber-a9: #f59a00f4;
206
+ --primitive-amber-a10: #e99300;
207
+ --primitive-amber-a11: #a35f00;
208
+ --primitive-amber-a12: #3f2300ea;
209
+ --primitive-amber-contrast: #4f3515;
210
+
211
+ --primitive-red-1: #faf7f6;
212
+ --primitive-red-2: #f9f2f1;
213
+ --primitive-red-3: #f9e5e2;
214
+ --primitive-red-4: #ffd4ce;
215
+ --primitive-red-5: #ffc5bd;
216
+ --primitive-red-6: #f9b4ab;
217
+ --primitive-red-7: #f19f95;
218
+ --primitive-red-8: #e88479;
219
+ --primitive-red-9: #dc2626;
220
+ --primitive-red-10: #cc0615;
221
+ --primitive-red-11: #ce0c17;
222
+ --primitive-red-12: #641c18;
223
+ --primitive-red-a1: #fb622f05;
224
+ --primitive-red-a2: #e12e150a;
225
+ --primitive-red-a3: #f0240619;
226
+ --primitive-red-a4: #ffd4ce;
227
+ --primitive-red-a5: #ffc5bd;
228
+ --primitive-red-a6: #f71d0151;
229
+ --primitive-red-a7: #e41b0368;
230
+ --primitive-red-a8: #d7160084;
231
+ --primitive-red-a9: #d70101d9;
232
+ --primitive-red-a10: #cb000ff9;
233
+ --primitive-red-a11: #cc000cf3;
234
+ --primitive-red-a12: #540400e7;
235
+ --primitive-red-contrast: #ffffff;
236
+ }
237
+
238
+ .dark {
239
+ /* hues — dark */
240
+ --primitive-blue-1: #050a16;
241
+ --primitive-blue-2: #0e1626;
242
+ --primitive-blue-3: #11244c;
243
+ --primitive-blue-4: #132e66;
244
+ --primitive-blue-5: #1a397a;
245
+ --primitive-blue-6: #22448b;
246
+ --primitive-blue-7: #2b509f;
247
+ --primitive-blue-8: #325ebb;
248
+ --primitive-blue-9: #2563eb;
249
+ --primitive-blue-10: #315dba;
250
+ --primitive-blue-11: #88b5ff;
251
+ --primitive-blue-12: #d1e2ff;
252
+ --primitive-blue-a1: #000af60d;
253
+ --primitive-blue-a2: #2c70f81e;
254
+ --primitive-blue-a3: #246bfe45;
255
+ --primitive-blue-a4: #226aff60;
256
+ --primitive-blue-a5: #2d71ff75;
257
+ --primitive-blue-a6: #3777fe87;
258
+ --primitive-blue-a7: #407dfe9c;
259
+ --primitive-blue-a8: #417efeb9;
260
+ --primitive-blue-a9: #276afeeb;
261
+ --primitive-blue-a10: #407dfeb8;
262
+ --primitive-blue-a11: #88b5ff;
263
+ --primitive-blue-a12: #d1e2ff;
264
+ --primitive-blue-contrast: #ffffff;
265
+
266
+ --primitive-green-1: #050c06;
267
+ --primitive-green-2: #101a12;
268
+ --primitive-green-3: #152b1a;
269
+ --primitive-green-4: #0f3c1d;
270
+ --primitive-green-5: #124b24;
271
+ --primitive-green-6: #155b2c;
272
+ --primitive-green-7: #166c34;
273
+ --primitive-green-8: #137f3c;
274
+ --primitive-green-9: #15803d;
275
+ --primitive-green-10: #1b6f37;
276
+ --primitive-green-11: #71d088;
277
+ --primitive-green-12: #acf7bb;
278
+ --primitive-green-a1: #00b40003;
279
+ --primitive-green-a2: #64fa8211;
280
+ --primitive-green-a3: #5bfb7f23;
281
+ --primitive-green-a4: #23fb6635;
282
+ --primitive-green-a5: #28fe6c44;
283
+ --primitive-green-a6: #2bfd7055;
284
+ --primitive-green-a7: #28ff7366;
285
+ --primitive-green-a8: #1dff737a;
286
+ --primitive-green-a9: #21ff747b;
287
+ --primitive-green-a10: #33fd776a;
288
+ --primitive-green-a11: #89fea5cf;
289
+ --primitive-green-a12: #b2ffc1f7;
290
+ --primitive-green-contrast: #ffffff;
291
+
292
+ --primitive-amber-1: #0d0906;
293
+ --primitive-amber-2: #1c150e;
294
+ --primitive-amber-3: #2f1f0c;
295
+ --primitive-amber-4: #412500;
296
+ --primitive-amber-5: #4e2e00;
297
+ --primitive-amber-6: #5d3c0f;
298
+ --primitive-amber-7: #724d1e;
299
+ --primitive-amber-8: #926426;
300
+ --primitive-amber-9: #f59e0b;
301
+ --primitive-amber-10: #e99300;
302
+ --primitive-amber-11: #fbb050;
303
+ --primitive-amber-12: #fde2c4;
304
+ --primitive-amber-a1: #ca000004;
305
+ --primitive-amber-a2: #fc9e4013;
306
+ --primitive-amber-a3: #fc941827;
307
+ --primitive-amber-a4: #fc81003a;
308
+ --primitive-amber-a5: #ff8c0047;
309
+ --primitive-amber-a6: #fd9c1857;
310
+ --primitive-amber-a7: #fda7396d;
311
+ --primitive-amber-a8: #ffac3d8e;
312
+ --primitive-amber-a9: #ffa40bf5;
313
+ --primitive-amber-a10: #fea000e9;
314
+ --primitive-amber-a11: #ffb351fb;
315
+ --primitive-amber-a12: #ffe4c6fd;
316
+ --primitive-amber-contrast: #4f3515;
140
317
 
141
- /* ── 6. SEMANTIC (dark foreground adjustments) ──────────────────────── */
142
- --alert-success-foreground: #86efac;
143
- --alert-success-foreground-muted: color-mix(
144
- in srgb,
145
- var(--alert-success-foreground) 85%,
146
- transparent
147
- );
148
- --alert-warning-foreground: #fde047;
149
- --alert-warning-foreground-muted: color-mix(
150
- in srgb,
151
- var(--alert-warning-foreground) 85%,
152
- transparent
153
- );
154
- --alert-error-foreground: #fca5a5;
155
- --alert-error-foreground-muted: color-mix(
156
- in srgb,
157
- var(--alert-error-foreground) 85%,
158
- transparent
159
- );
160
- --alert-info-foreground: #93c5fd;
161
- --alert-info-foreground-muted: color-mix(in srgb, var(--alert-info-foreground) 85%, transparent);
318
+ --primitive-red-1: #100807;
319
+ --primitive-red-2: #1f1210;
320
+ --primitive-red-3: #3c110e;
321
+ --primitive-red-4: #530b0a;
322
+ --primitive-red-5: #641210;
323
+ --primitive-red-6: #76201c;
324
+ --primitive-red-7: #8f312a;
325
+ --primitive-red-8: #b94038;
326
+ --primitive-red-9: #dc2626;
327
+ --primitive-red-10: #b63d36;
328
+ --primitive-red-11: #ff9083;
329
+ --primitive-red-12: #ffd1ca;
330
+ --primitive-red-a1: #e5000007;
331
+ --primitive-red-a2: #fe675016;
332
+ --primitive-red-a3: #fb2c1e35;
333
+ --primitive-red-a4: #ff0e0a4c;
334
+ --primitive-red-a5: #ff201b5e;
335
+ --primitive-red-a6: #fd3b3271;
336
+ --primitive-red-a7: #fe51448b;
337
+ --primitive-red-a8: #fe554ab7;
338
+ --primitive-red-a9: #ff2b2bdb;
339
+ --primitive-red-a10: #fe5248b4;
340
+ --primitive-red-a11: #ff9083;
341
+ --primitive-red-a12: #ffd1ca;
342
+ --primitive-red-contrast: #ffffff;
343
+ }
344
+
345
+ /*
346
+ * 7. SEMANTIC — product-wide; inherited by all palettes, do not override.
347
+ *
348
+ * Declared for both `:root` and `.dark` so a nested `.dark` wrapper re-resolves
349
+ * the roles against its own hue scales (6). The values are identical in both
350
+ * selectors; only the hue scales differ per mode. The one per-mode exception,
351
+ * `--warning-text`, is declared in the `.dark` rule after this block.
352
+ *
353
+ * Roles: `--{info|success|warning|danger|neutral}-{surface|surface-hover|
354
+ * border|solid|solid-hover|text|contrast|indicator}`. Hue intents read the hue
355
+ * scales; `neutral` reads the system tokens. `--status-*` and `--alert-*` below
356
+ * are aliases of these roles, so both families agree by construction.
357
+ */
358
+ :root,
359
+ .dark {
360
+ --neutral-surface: var(--muted);
361
+ --neutral-surface-hover: var(--accent);
362
+ --neutral-border: var(--border);
363
+ --neutral-solid: var(--secondary);
364
+ --neutral-solid-hover: var(--accent);
365
+ --neutral-text: var(--foreground);
366
+ --neutral-contrast: var(--secondary-foreground);
367
+ --neutral-indicator: var(--muted-foreground);
368
+ --info-surface: var(--primitive-blue-a3);
369
+ --info-surface-hover: var(--primitive-blue-a4);
370
+ --info-border: var(--primitive-blue-a6);
371
+ --info-solid: var(--primitive-blue-9);
372
+ --info-solid-hover: var(--primitive-blue-10);
373
+ --info-text: var(--primitive-blue-11);
374
+ --info-contrast: var(--primitive-blue-contrast);
375
+ --info-indicator: var(--primitive-blue-9);
376
+ --success-surface: var(--primitive-green-a3);
377
+ --success-surface-hover: var(--primitive-green-a4);
378
+ --success-border: var(--primitive-green-a6);
379
+ --success-solid: var(--primitive-green-9);
380
+ --success-solid-hover: var(--primitive-green-10);
381
+ --success-text: var(--primitive-green-11);
382
+ --success-contrast: var(--primitive-green-contrast);
383
+ --success-indicator: var(--primitive-green-9);
384
+ --warning-surface: var(--primitive-amber-a3);
385
+ --warning-surface-hover: var(--primitive-amber-a4);
386
+ --warning-border: var(--primitive-amber-a6);
387
+ --warning-solid: var(--primitive-amber-9);
388
+ --warning-solid-hover: var(--primitive-amber-10);
389
+ --warning-text: var(--primitive-amber-12);
390
+ --warning-contrast: var(--primitive-amber-contrast);
391
+ --warning-indicator: var(--primitive-amber-9);
392
+ --danger-surface: var(--primitive-red-a3);
393
+ --danger-surface-hover: var(--primitive-red-a4);
394
+ --danger-border: var(--primitive-red-a6);
395
+ --danger-solid: var(--primitive-red-9);
396
+ --danger-solid-hover: var(--primitive-red-10);
397
+ --danger-text: var(--primitive-red-11);
398
+ --danger-contrast: var(--primitive-red-contrast);
399
+ --danger-indicator: var(--primitive-red-9);
400
+
401
+ --status-default: var(--neutral-indicator);
402
+ --status-neutral: var(--info-solid);
403
+ --status-completed: var(--success-solid);
404
+ --status-attention: var(--warning-solid);
405
+ --status-danger: var(--danger-solid);
406
+ --alert-neutral-background: var(--neutral-surface);
407
+ --alert-neutral-foreground: var(--neutral-text);
408
+ --alert-neutral-foreground-muted: var(--muted-foreground);
409
+ --alert-neutral-border: var(--neutral-border);
410
+ --alert-success-background: var(--success-surface);
411
+ --alert-success-foreground: var(--success-text);
412
+ --alert-success-foreground-muted: var(--alert-success-foreground);
413
+ --alert-success-border: var(--success-border);
414
+ --alert-warning-background: var(--warning-surface);
415
+ --alert-warning-foreground: var(--warning-text);
416
+ --alert-warning-foreground-muted: var(--alert-warning-foreground);
417
+ --alert-warning-border: var(--warning-border);
418
+ --alert-error-background: var(--danger-surface);
419
+ --alert-error-foreground: var(--danger-text);
420
+ --alert-error-foreground-muted: var(--alert-error-foreground);
421
+ --alert-error-border: var(--danger-border);
422
+ --alert-info-background: var(--info-surface);
423
+ --alert-info-foreground: var(--info-text);
424
+ --alert-info-foreground-muted: var(--alert-info-foreground);
425
+ --alert-info-border: var(--info-border);
426
+ }
427
+
428
+ .dark {
429
+ /* Warning text: step 12 on the light surface, step 11 on the dark one. */
430
+ --warning-text: var(--primitive-amber-11);
431
+ }
432
+
433
+ /*
434
+ * 8. TYPOGRAPHY — composite roles; light only, no dark variant.
435
+ *
436
+ * Four variables per role: size, line-height (unitless ratio), weight and
437
+ * letter-spacing. theme.bridge.css maps them to `text-<role>` utilities.
438
+ * Palettes inherit these; override `--app-shell-type-*` on `:root` to change
439
+ * a role. See decisions/typography-roles.md.
440
+ */
441
+ :root {
442
+ --app-shell-type-heading-lg-size: 1.5rem;
443
+ --app-shell-type-heading-lg-line-height: calc(32 / 24);
444
+ --app-shell-type-heading-lg-weight: 700;
445
+ --app-shell-type-heading-lg-letter-spacing: -0.025em;
446
+ --app-shell-type-heading-md-size: 1.125rem;
447
+ --app-shell-type-heading-md-line-height: calc(28 / 18);
448
+ --app-shell-type-heading-md-weight: 600;
449
+ --app-shell-type-heading-md-letter-spacing: 0em;
450
+ --app-shell-type-heading-sm-size: 0.875rem;
451
+ --app-shell-type-heading-sm-line-height: calc(20 / 14);
452
+ --app-shell-type-heading-sm-weight: 600;
453
+ --app-shell-type-heading-sm-letter-spacing: 0em;
454
+ --app-shell-type-body-md-size: 0.875rem;
455
+ --app-shell-type-body-md-line-height: calc(20 / 14);
456
+ --app-shell-type-body-md-weight: 400;
457
+ --app-shell-type-body-md-letter-spacing: 0em;
458
+ --app-shell-type-body-sm-size: 0.75rem;
459
+ --app-shell-type-body-sm-line-height: calc(16 / 12);
460
+ --app-shell-type-body-sm-weight: 400;
461
+ --app-shell-type-body-sm-letter-spacing: 0em;
462
+ --app-shell-type-label-md-size: 0.875rem;
463
+ --app-shell-type-label-md-line-height: calc(20 / 14);
464
+ --app-shell-type-label-md-weight: 500;
465
+ --app-shell-type-label-md-letter-spacing: 0em;
466
+ --app-shell-type-label-sm-size: 0.75rem;
467
+ --app-shell-type-label-sm-line-height: calc(16 / 12);
468
+ --app-shell-type-label-sm-weight: 500;
469
+ --app-shell-type-label-sm-letter-spacing: 0em;
470
+ --app-shell-type-code-sm-size: 0.75rem;
471
+ --app-shell-type-code-sm-line-height: calc(18 / 12);
472
+ --app-shell-type-code-sm-weight: 400;
473
+ --app-shell-type-code-sm-letter-spacing: 0em;
474
+ --app-shell-type-body-md-relaxed-size: 0.875rem;
475
+ --app-shell-type-body-md-relaxed-line-height: calc(24 / 14);
476
+ --app-shell-type-body-md-relaxed-weight: 400;
477
+ --app-shell-type-body-md-relaxed-letter-spacing: 0em;
478
+ --app-shell-type-body-sm-relaxed-size: 0.75rem;
479
+ --app-shell-type-body-sm-relaxed-line-height: calc(20 / 12);
480
+ --app-shell-type-body-sm-relaxed-weight: 400;
481
+ --app-shell-type-body-sm-relaxed-letter-spacing: 0em;
162
482
  }