@brightweblabs/theme 0.3.0 → 0.4.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.
- package/README.md +58 -0
- package/package.json +1 -1
- package/src/base.css +25 -1
- package/src/surfaces.css +54 -53
- package/src/theme.css +40 -0
- package/src/tokens.css +167 -17
- package/src/typography.css +35 -56
- package/themes/mq-aliases.css +95 -53
- package/themes/mq.css +28 -4
package/README.md
CHANGED
|
@@ -2,10 +2,65 @@
|
|
|
2
2
|
|
|
3
3
|
BrightWeb themes follow one cascade: L0 brand primitives feed L1 shadcn semantics, L2 describes brand-agnostic states, and L3 exposes component and experience controls. Package components consume L1-L3 tokens only; theme files such as `themes/mq.css` override values without changing component code.
|
|
4
4
|
|
|
5
|
+
## Typography and font loading
|
|
6
|
+
|
|
7
|
+
Geist is the offline-safe platform default. Applications load `GeistSans` and `GeistMono` from the `geist/font` package and attach their variables to the app root (the platform layout uses `<body>`):
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { GeistMono } from "geist/font/mono";
|
|
11
|
+
import { GeistSans } from "geist/font/sans";
|
|
12
|
+
|
|
13
|
+
<body className={`${GeistSans.variable} ${GeistMono.variable}`}>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The family contract starts at `--font-body`, `--font-heading`, and `--font-code`; Tailwind-facing `--font-sans`, `--font-display`, and `--font-mono` aliases resolve through those tokens. Raw sizes live only in the `--text-ui-*`, `--type-*`, weight, leading, and tracking scales in `src/tokens.css`. Components consume semantic utilities such as `text-ui-body`, `portal-title`, and `heading-2`, so changing a family or scale does not require component edits.
|
|
17
|
+
|
|
18
|
+
Client themes can override the family without forking recipes. The MQ path is:
|
|
19
|
+
|
|
20
|
+
```css
|
|
21
|
+
@import "@brightweblabs/theme/css";
|
|
22
|
+
@import "@brightweblabs/theme/themes/mq";
|
|
23
|
+
@import "@brightweblabs/theme/themes/mq-aliases";
|
|
24
|
+
|
|
25
|
+
:root {
|
|
26
|
+
--font-client-body: "Mulish", sans-serif;
|
|
27
|
+
--font-body: var(--font-client-body);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`themes/mq.css` supplies MQ color and surface values, while `themes/mq-aliases.css` maps legacy MQ typography names onto the same tokenized scale. Import the MQ stylesheet after the base theme. Keep font loading at the app root; theme packages only select variables and never fetch fonts.
|
|
32
|
+
|
|
33
|
+
## Runtime theme switching
|
|
34
|
+
|
|
35
|
+
Theme tokens respond to both `html.dark` and `html[data-theme="dark"]`. Platform apps should use the shell-owned controller so those selectors never drift:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { ThemeProvider, ThemeScript } from "@brightweblabs/app-shell";
|
|
39
|
+
|
|
40
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
41
|
+
return (
|
|
42
|
+
<html lang="en" suppressHydrationWarning>
|
|
43
|
+
<head>
|
|
44
|
+
<ThemeScript defaultTheme="light" />
|
|
45
|
+
</head>
|
|
46
|
+
<body>
|
|
47
|
+
<ThemeProvider defaultTheme="light">{children}</ThemeProvider>
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`ThemeScript` applies the stored `bw-theme` mode before hydration to prevent a light-theme flash. `ThemeProvider` keeps the root class, `data-theme`, and `color-scheme` synchronized, persists `"light" | "dark" | "system"`, and follows `prefers-color-scheme` while system mode is selected. Account menus rendered below the provider use this controller automatically.
|
|
55
|
+
|
|
5
56
|
## L3 visual tokens
|
|
6
57
|
|
|
7
58
|
| Tokens | Purpose |
|
|
8
59
|
| --- | --- |
|
|
60
|
+
| `--font-body`, `--font-heading`, `--font-code`; `--font-sans`, `--font-display`, `--font-mono` | Root font families and their Tailwind-facing aliases. |
|
|
61
|
+
| `--type-weight-*`, `--type-leading-*`, `--type-tracking-*` | Shared typography weight, rhythm, and tracking primitives. |
|
|
62
|
+
| `--text-ui-*`, `--type-paragraph*`, `--type-heading-2`, `--type-label` | Tokenized platform and compatibility type scales. |
|
|
63
|
+
| `--foreground-muted-accessible`, `--foreground-inverse-muted`, `--foreground-inverse-subtle` | Contrast-safe secondary and inverse text roles. |
|
|
9
64
|
| `--text-ui-chip`, `--text-ui-action`, `--text-ui-calendar` | Compact control and calendar type sizes. |
|
|
10
65
|
| `--text-ui-shell-title`, `--text-ui-report-title`, `--text-ui-report-title-lg`, `--text-ui-report-metric` | Shell and CRM report display type sizes. |
|
|
11
66
|
| `--surface-overlay`, `--surface-overlay-strong`, `--surface-tooltip`, `--surface-badge-tint` | Overlay, tooltip, and tint surfaces. |
|
|
@@ -15,6 +70,7 @@ BrightWeb themes follow one cascade: L0 brand primitives feed L1 shadcn semantic
|
|
|
15
70
|
| `--surface-account-team`, `--surface-account-client`, `--surface-account`, `--surface-account-hover`, `--account-presence` | Account rail identity, presence, and interaction surfaces. |
|
|
16
71
|
| `--account-presence-size`, `--radius-swatch`, `--radius-pill`, `--radius-scrollbar` | Presence, swatch, pill, avatar, and scrollbar geometry. |
|
|
17
72
|
| `--row-hover-sweep`, `--surface-status-success`, `--surface-status-warning`, `--surface-status-danger` | Shared row and status surfaces. |
|
|
73
|
+
| `--dashboard-*` | Aggregate dashboard glows, shadows, task groups, milestone states, and local shell contrast recipes. |
|
|
18
74
|
| `--tint-soft-border`, `--tint-soft-bg`, `--tint-soft-hover`, `--tint-hero-border`, `--tint-hero-bg`, `--tint-hero-fg`, `--tint-hero-hover` | Dynamic tint recipes resolved where a component supplies `--tint`. |
|
|
19
75
|
| `--scrollbar-thumb`, `--scrollbar-thumb-hover`, `--scrollbar-size` | Shared scrollbar colour and geometry. |
|
|
20
76
|
| `--toast-success-bg`, `--toast-success-border`, `--toast-warning-bg`, `--toast-warning-text`, `--toast-warning-border`, `--toast-error-bg`, `--toast-error-border`, `--toast-info-bg`, `--toast-info-text`, `--toast-info-border` | Sonner semantic toast palette. |
|
|
@@ -36,3 +92,5 @@ BrightWeb themes follow one cascade: L0 brand primitives feed L1 shadcn semantic
|
|
|
36
92
|
| `--section-icon-size`, `--surface-enter-offset`, `--space-eyebrow-y` | Shared surface icon, entrance, and eyebrow geometry. |
|
|
37
93
|
|
|
38
94
|
All tokens above have neutral defaults in `src/tokens.css`. Values that are derived from semantic tokens automatically follow `themes/mq.css`; a direct MQ declaration is needed only when MQ intentionally differs from the neutral default. `themes/mq-aliases.css` remains the compatibility layer for legacy MQ primitive and typography names.
|
|
95
|
+
|
|
96
|
+
The base stylesheet also provides the global `prefers-reduced-motion: reduce` contract. It disables smooth scrolling and collapses animation and transition timing; skeleton and package styles add static fallbacks where their animated state would otherwise remain off-screen or transparent.
|
package/package.json
CHANGED
package/src/base.css
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
padding: 0;
|
|
15
15
|
background: var(--page-background);
|
|
16
16
|
color: var(--foreground);
|
|
17
|
-
font-family: var(--font-sans)
|
|
17
|
+
font-family: var(--font-sans);
|
|
18
18
|
-webkit-font-smoothing: antialiased;
|
|
19
19
|
-moz-osx-font-smoothing: grayscale;
|
|
20
20
|
text-rendering: optimizeLegibility;
|
|
@@ -31,4 +31,28 @@
|
|
|
31
31
|
input {
|
|
32
32
|
font: inherit;
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
/* Hand-rolled controls keep a visible keyboard state. Component utilities
|
|
36
|
+
can replace this fallback with their own focus-visible treatment. */
|
|
37
|
+
:where(button, a[href], [role="button"]):focus-visible {
|
|
38
|
+
outline: 2px solid currentColor;
|
|
39
|
+
outline-offset: 2px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@media (prefers-reduced-motion: reduce) {
|
|
43
|
+
html {
|
|
44
|
+
scroll-behavior: auto !important;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
*,
|
|
48
|
+
::before,
|
|
49
|
+
::after {
|
|
50
|
+
animation-delay: 0ms !important;
|
|
51
|
+
animation-duration: 0ms !important;
|
|
52
|
+
animation-iteration-count: 1 !important;
|
|
53
|
+
scroll-behavior: auto !important;
|
|
54
|
+
transition-delay: 0ms !important;
|
|
55
|
+
transition-duration: 0ms !important;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
34
58
|
}
|
package/src/surfaces.css
CHANGED
|
@@ -1,42 +1,47 @@
|
|
|
1
1
|
/* ── Shared structural surfaces ───────────────────────────────────────── */
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
/* Layered so Tailwind utilities (p-0, bg-*, …) can override per-instance.
|
|
3
|
+
Unlayered, these beat @layer utilities and e.g. p-0 on the CRM table card
|
|
4
|
+
silently loses to the default card padding. */
|
|
5
|
+
@layer components {
|
|
6
|
+
.surface-card {
|
|
7
|
+
border-radius: var(--radius-card);
|
|
8
|
+
border: 1px solid var(--border-hairline);
|
|
9
|
+
background: var(--surface-card);
|
|
10
|
+
padding: var(--surface-card-padding);
|
|
11
|
+
animation: surface-fade-in 640ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
|
|
12
|
+
}
|
|
9
13
|
|
|
10
|
-
.surface-card.is-light {
|
|
11
|
-
|
|
12
|
-
}
|
|
14
|
+
.surface-card.is-light {
|
|
15
|
+
background: var(--surface-card-light);
|
|
16
|
+
}
|
|
13
17
|
|
|
14
|
-
/* A near-black panel has strong figure/ground in light mode. In dark mode it
|
|
15
|
-
|
|
16
|
-
.brand-panel {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
18
|
+
/* A near-black panel has strong figure/ground in light mode. In dark mode it
|
|
19
|
+
elevates above the page through a lighter accent mix, border, and shadow. */
|
|
20
|
+
.brand-panel {
|
|
21
|
+
--row-sweep-tint: var(--brand-panel-foreground);
|
|
22
|
+
background: var(--brand-panel-surface);
|
|
23
|
+
}
|
|
20
24
|
|
|
21
|
-
.dark .brand-panel,
|
|
22
|
-
.theme-dark .brand-panel {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
25
|
+
.dark .brand-panel,
|
|
26
|
+
.theme-dark .brand-panel {
|
|
27
|
+
border: 1px solid var(--brand-panel-border);
|
|
28
|
+
box-shadow: var(--brand-shadow-lift);
|
|
29
|
+
}
|
|
26
30
|
|
|
27
|
-
.row-hover-sweep {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
31
|
+
.row-hover-sweep {
|
|
32
|
+
pointer-events: none;
|
|
33
|
+
position: absolute;
|
|
34
|
+
inset: 0;
|
|
35
|
+
border-radius: var(--radius-card);
|
|
36
|
+
opacity: 0;
|
|
37
|
+
transition: opacity 300ms ease;
|
|
38
|
+
background: var(--row-hover-sweep);
|
|
39
|
+
}
|
|
36
40
|
|
|
37
|
-
.group:hover > .row-hover-sweep,
|
|
38
|
-
.group:focus-visible > .row-hover-sweep {
|
|
39
|
-
|
|
41
|
+
.group:hover > .row-hover-sweep,
|
|
42
|
+
.group:focus-visible > .row-hover-sweep {
|
|
43
|
+
opacity: 1;
|
|
44
|
+
}
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
/* ── Canonical tinted-pill recipes ────────────────────────────────────── */
|
|
@@ -62,7 +67,8 @@
|
|
|
62
67
|
}
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
@layer components {
|
|
71
|
+
.section-icon {
|
|
66
72
|
display: flex;
|
|
67
73
|
width: var(--section-icon-size);
|
|
68
74
|
height: var(--section-icon-size);
|
|
@@ -74,11 +80,12 @@
|
|
|
74
80
|
color: var(--muted-foreground);
|
|
75
81
|
}
|
|
76
82
|
|
|
77
|
-
.stat-cell {
|
|
78
|
-
|
|
83
|
+
.stat-cell {
|
|
84
|
+
padding: var(--stat-cell-padding);
|
|
85
|
+
}
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
/* Skeleton shimmer
|
|
88
|
+
/* Skeleton shimmer becomes a static surface under reduced motion. */
|
|
82
89
|
@keyframes surface-fade-in {
|
|
83
90
|
from {
|
|
84
91
|
opacity: 0;
|
|
@@ -96,17 +103,8 @@
|
|
|
96
103
|
}
|
|
97
104
|
}
|
|
98
105
|
|
|
99
|
-
@
|
|
100
|
-
|
|
101
|
-
100% {
|
|
102
|
-
opacity: 1;
|
|
103
|
-
}
|
|
104
|
-
50% {
|
|
105
|
-
opacity: 0.6;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.skeleton-ghost {
|
|
106
|
+
@layer components {
|
|
107
|
+
.skeleton-ghost {
|
|
110
108
|
position: relative;
|
|
111
109
|
overflow: hidden;
|
|
112
110
|
background: var(--skeleton);
|
|
@@ -127,7 +125,9 @@
|
|
|
127
125
|
}
|
|
128
126
|
|
|
129
127
|
.skeleton-ghost {
|
|
130
|
-
animation:
|
|
128
|
+
animation: none;
|
|
129
|
+
opacity: 1;
|
|
130
|
+
transform: none;
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
color: var(--brand-accent);
|
|
141
141
|
font-size: var(--text-ui-label);
|
|
142
142
|
font-weight: var(--font-weight-bold);
|
|
143
|
-
letter-spacing:
|
|
143
|
+
letter-spacing: var(--type-tracking-040);
|
|
144
144
|
text-transform: uppercase;
|
|
145
145
|
}
|
|
146
146
|
|
|
@@ -164,7 +164,8 @@
|
|
|
164
164
|
color: var(--semantic-warning-strong);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
.status.error {
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
.status.error {
|
|
168
|
+
background: var(--surface-status-danger);
|
|
169
|
+
color: var(--semantic-danger-strong);
|
|
170
|
+
}
|
|
170
171
|
}
|
package/src/theme.css
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
13
13
|
--color-muted: var(--muted);
|
|
14
14
|
--color-muted-foreground: var(--muted-foreground);
|
|
15
|
+
--color-foreground-muted-accessible: var(--foreground-muted-accessible);
|
|
15
16
|
--color-accent: var(--accent);
|
|
16
17
|
--color-accent-foreground: var(--accent-foreground);
|
|
17
18
|
--color-destructive: var(--destructive);
|
|
@@ -83,6 +84,45 @@
|
|
|
83
84
|
--radius-2xl: var(--radius-panel);
|
|
84
85
|
--radius-3xl: var(--radius-panel);
|
|
85
86
|
|
|
87
|
+
/* Tailwind typography utilities resolve through the same token contract. */
|
|
88
|
+
--font-sans: var(--font-body);
|
|
89
|
+
--font-display: var(--font-heading);
|
|
90
|
+
--font-mono: var(--font-code);
|
|
91
|
+
--font-weight-regular: var(--type-weight-regular);
|
|
92
|
+
--font-weight-normal: var(--type-weight-regular);
|
|
93
|
+
--font-weight-medium: var(--type-weight-medium);
|
|
94
|
+
--font-weight-semibold: var(--type-weight-medium);
|
|
95
|
+
--font-weight-bold: var(--type-weight-bold);
|
|
96
|
+
--font-weight-heavy: var(--type-weight-heavy);
|
|
97
|
+
--font-weight-extrabold: var(--type-weight-heavy);
|
|
98
|
+
--font-weight-black: var(--type-weight-black);
|
|
99
|
+
--text-xs: var(--text-ui-meta);
|
|
100
|
+
--text-xs--line-height: var(--type-leading-133);
|
|
101
|
+
--text-sm: var(--text-ui-body);
|
|
102
|
+
--text-sm--line-height: var(--type-leading-143);
|
|
103
|
+
--text-base: var(--type-paragraph);
|
|
104
|
+
--text-base--line-height: var(--type-leading-normal);
|
|
105
|
+
--text-lg: var(--text-ui-subhead);
|
|
106
|
+
--text-lg--line-height: var(--type-leading-156);
|
|
107
|
+
--text-xl: var(--text-ui-panel-title);
|
|
108
|
+
--text-xl--line-height: var(--type-leading-140);
|
|
109
|
+
--text-2xl: var(--text-ui-heading);
|
|
110
|
+
--text-2xl--line-height: var(--type-leading-133);
|
|
111
|
+
--text-3xl: var(--text-ui-title-sm);
|
|
112
|
+
--text-3xl--line-height: var(--type-leading-120);
|
|
113
|
+
--leading-none: var(--type-leading-none);
|
|
114
|
+
--leading-tight: var(--type-leading-tight);
|
|
115
|
+
--leading-snug: var(--type-leading-snug);
|
|
116
|
+
--leading-normal: var(--type-leading-normal);
|
|
117
|
+
--leading-relaxed: var(--type-leading-relaxed);
|
|
118
|
+
--leading-loose: var(--type-leading-loose);
|
|
119
|
+
--tracking-tighter: var(--type-tracking-n050);
|
|
120
|
+
--tracking-tight: var(--type-tracking-tight);
|
|
121
|
+
--tracking-normal: var(--type-tracking-normal);
|
|
122
|
+
--tracking-wide: var(--type-tracking-wide);
|
|
123
|
+
--tracking-wider: var(--type-tracking-wider);
|
|
124
|
+
--tracking-widest: var(--type-tracking-widest);
|
|
125
|
+
|
|
86
126
|
/* Named spacing keys sit alongside Tailwind's numeric scale. */
|
|
87
127
|
--spacing-2xs: var(--space-2xs);
|
|
88
128
|
--spacing-xs: var(--space-xs);
|
package/src/tokens.css
CHANGED
|
@@ -1,11 +1,75 @@
|
|
|
1
1
|
/* ── L0: brand primitives ─────────────────────────────────────────────── */
|
|
2
2
|
:root {
|
|
3
3
|
color-scheme: light;
|
|
4
|
-
|
|
4
|
+
/* Font loaders expose these variables at the app root. Client themes only
|
|
5
|
+
override this family layer; component recipes never name a font. The system
|
|
6
|
+
fallback after the loaded-font var is REQUIRED: without it a missing
|
|
7
|
+
--font-geist-sans makes the whole var() chain "guaranteed-invalid" and
|
|
8
|
+
font-family silently reverts to the browser default (Times), instead of a
|
|
9
|
+
clean sans. */
|
|
10
|
+
--font-body: var(--font-geist-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);
|
|
5
11
|
--font-heading: var(--font-body);
|
|
6
|
-
--font-
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
--font-code: var(--font-geist-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace);
|
|
13
|
+
|
|
14
|
+
/* Typography primitives. These raw values live here—and only here—so a
|
|
15
|
+
maintainer can retune family, scale, weight, rhythm, or tracking globally. */
|
|
16
|
+
--type-weight-regular: 400;
|
|
17
|
+
--type-weight-medium: 600;
|
|
18
|
+
--type-weight-bold: 700;
|
|
19
|
+
--type-weight-heavy: 800;
|
|
20
|
+
--type-weight-black: 900;
|
|
21
|
+
|
|
22
|
+
--type-leading-090: 0.9;
|
|
23
|
+
--type-leading-092: 0.92;
|
|
24
|
+
--type-leading-095: 0.95;
|
|
25
|
+
--type-leading-096: 0.96;
|
|
26
|
+
--type-leading-none: 1;
|
|
27
|
+
--type-leading-102: 1.02;
|
|
28
|
+
--type-leading-104: 1.04;
|
|
29
|
+
--type-leading-105: 1.05;
|
|
30
|
+
--type-leading-110: 1.1;
|
|
31
|
+
--type-leading-115: 1.15;
|
|
32
|
+
--type-leading-120: 1.2;
|
|
33
|
+
--type-leading-124: 1.238;
|
|
34
|
+
--type-leading-tight: 1.25;
|
|
35
|
+
--type-leading-130: 1.3;
|
|
36
|
+
--type-leading-133: calc(1 / 0.75);
|
|
37
|
+
--type-leading-snug: 1.375;
|
|
38
|
+
--type-leading-140: 1.4;
|
|
39
|
+
--type-leading-143: calc(1.25 / 0.875);
|
|
40
|
+
--type-leading-145: 1.45;
|
|
41
|
+
--type-leading-normal: 1.5;
|
|
42
|
+
--type-leading-155: 1.55;
|
|
43
|
+
--type-leading-156: calc(1.75 / 1.125);
|
|
44
|
+
--type-leading-160: 1.6;
|
|
45
|
+
--type-leading-relaxed: 1.625;
|
|
46
|
+
--type-leading-165: 1.65;
|
|
47
|
+
--type-leading-166: 1.66;
|
|
48
|
+
--type-leading-172: 1.72;
|
|
49
|
+
--type-leading-loose: 2;
|
|
50
|
+
|
|
51
|
+
--type-tracking-n050: -0.05em;
|
|
52
|
+
--type-tracking-n045: -0.045em;
|
|
53
|
+
--type-tracking-n040: -0.04em;
|
|
54
|
+
--type-tracking-n035: -0.035em;
|
|
55
|
+
--type-tracking-n030: -0.03em;
|
|
56
|
+
--type-tracking-n025: -0.025em;
|
|
57
|
+
--type-tracking-n020: -0.02em;
|
|
58
|
+
--type-tracking-tight: -0.025em;
|
|
59
|
+
--type-tracking-n010: -0.01em;
|
|
60
|
+
--type-tracking-normal: 0;
|
|
61
|
+
--type-tracking-010: 0.01em;
|
|
62
|
+
--type-tracking-wide: 0.025em;
|
|
63
|
+
--type-tracking-040: 0.04em;
|
|
64
|
+
--type-tracking-wider: 0.05em;
|
|
65
|
+
--type-tracking-060: 0.06em;
|
|
66
|
+
--type-tracking-080: 0.08em;
|
|
67
|
+
--type-tracking-100: 0.1em;
|
|
68
|
+
--type-tracking-120: 0.12em;
|
|
69
|
+
--type-tracking-140: 0.14em;
|
|
70
|
+
--type-tracking-160: 0.16em;
|
|
71
|
+
--type-tracking-widest: 0.1em;
|
|
72
|
+
--type-tracking-180: 0.18em;
|
|
9
73
|
|
|
10
74
|
--brand-accent: #4a7dbd;
|
|
11
75
|
--brand-accent-soft: #7196c4;
|
|
@@ -34,6 +98,7 @@
|
|
|
34
98
|
--secondary-foreground: var(--brand-ink);
|
|
35
99
|
--muted: rgba(203, 213, 225, 0.25);
|
|
36
100
|
--muted-foreground: var(--brand-neutral-500);
|
|
101
|
+
--foreground-muted-accessible: #5f6b7a;
|
|
37
102
|
--foreground-inverse: var(--brand-white);
|
|
38
103
|
--foreground-inverse-muted: rgba(255, 255, 255, 0.88);
|
|
39
104
|
--foreground-inverse-subtle: rgba(255, 255, 255, 0.84);
|
|
@@ -60,6 +125,34 @@
|
|
|
60
125
|
--semantic-neutral: #71717a;
|
|
61
126
|
--semantic-neutral-strong: #52525b;
|
|
62
127
|
|
|
128
|
+
--project-state-planned: var(--semantic-info);
|
|
129
|
+
--project-state-planned-strong: var(--semantic-info-strong);
|
|
130
|
+
--project-state-active: var(--semantic-success);
|
|
131
|
+
--project-state-active-strong: var(--semantic-success-strong);
|
|
132
|
+
--project-state-blocked: var(--semantic-special);
|
|
133
|
+
--project-state-blocked-strong: var(--semantic-special-strong);
|
|
134
|
+
--project-state-completed: var(--semantic-success);
|
|
135
|
+
--project-state-completed-strong: var(--semantic-success-strong);
|
|
136
|
+
--project-state-canceled: var(--semantic-neutral);
|
|
137
|
+
--project-state-canceled-strong: var(--semantic-neutral-strong);
|
|
138
|
+
--project-risk-at-risk: var(--semantic-warning);
|
|
139
|
+
--project-risk-at-risk-strong: var(--semantic-warning-strong);
|
|
140
|
+
--project-risk-overdue: var(--semantic-danger);
|
|
141
|
+
--project-risk-overdue-strong: var(--semantic-danger-strong);
|
|
142
|
+
--project-risk-overdue-soft: var(--semantic-danger-soft);
|
|
143
|
+
/* Ink to use ON a solid health fill: light-mode fills are saturated so
|
|
144
|
+
ink flips per theme (see dark block). */
|
|
145
|
+
--project-risk-overdue-ink: #ffffff;
|
|
146
|
+
--project-risk-at-risk-ink: #3a2a05;
|
|
147
|
+
--project-state-completed-ink: #06281e;
|
|
148
|
+
--project-health-on-track: var(--project-state-active-strong);
|
|
149
|
+
--project-health-at-risk: var(--project-risk-at-risk);
|
|
150
|
+
--project-health-at-risk-strong: var(--project-risk-at-risk-strong);
|
|
151
|
+
--project-health-off-track: var(--project-risk-overdue);
|
|
152
|
+
--project-health-progress: var(--project-state-active);
|
|
153
|
+
--project-health-off-track-strong: var(--project-risk-overdue-strong);
|
|
154
|
+
--project-health-off-track-soft: var(--project-risk-overdue-soft);
|
|
155
|
+
|
|
63
156
|
/* ── L3: experience tokens ─────────────────────────────────────────── */
|
|
64
157
|
--space-2xs: 0.25rem;
|
|
65
158
|
--space-xs: 0.5rem;
|
|
@@ -89,8 +182,13 @@
|
|
|
89
182
|
--radius-pill: 999px;
|
|
90
183
|
--radius-scrollbar: 9999px;
|
|
91
184
|
|
|
185
|
+
/* MQ-derived size scale. Aliases below retain the current rendered sizes. */
|
|
186
|
+
--text-ui-nano: 0.4375rem;
|
|
187
|
+
--text-ui-nano-lg: 0.5rem;
|
|
188
|
+
--text-ui-fine: 0.5625rem;
|
|
92
189
|
--text-ui-micro: 0.625rem;
|
|
93
190
|
--text-ui-label: 0.6875rem;
|
|
191
|
+
--text-ui-label-relaxed: 0.7rem;
|
|
94
192
|
--text-ui-meta: 0.75rem;
|
|
95
193
|
--text-ui-chip: 0.78125rem;
|
|
96
194
|
--text-ui-action: 0.8125rem;
|
|
@@ -108,22 +206,22 @@
|
|
|
108
206
|
--text-ui-report-metric: 2.5rem;
|
|
109
207
|
--text-ui-metric: 2.75rem;
|
|
110
208
|
--text-ui-metric-xl: 3.5rem;
|
|
209
|
+
--text-ui-dashboard-card-title: 1.375rem;
|
|
210
|
+
--text-ui-dashboard-title: 2.125rem;
|
|
211
|
+
--text-ui-preview-card-title: 2.375rem;
|
|
212
|
+
--text-ui-dashboard-title-lg: 2.75rem;
|
|
213
|
+
--text-ui-dashboard-metric: 3.25rem;
|
|
214
|
+
--text-ui-preview-stat: clamp(2rem, 4vw, 3rem);
|
|
215
|
+
--text-ui-preview-title: clamp(2.4rem, 5.5vw, 4.8rem);
|
|
216
|
+
--text-ui-auth-title: clamp(2.4rem, 5vw, 4.75rem);
|
|
111
217
|
--text-ui-metric-display: var(--text-ui-metric);
|
|
112
218
|
--portal-text-micro: 0.625rem;
|
|
113
|
-
--portal-text-label: 0.6875rem;
|
|
114
|
-
--portal-text-meta: 0.75rem;
|
|
115
|
-
--portal-text-body: 0.875rem;
|
|
116
|
-
--portal-text-card-title: 0.9375rem;
|
|
117
|
-
--portal-text-subhead: 1.125rem;
|
|
118
|
-
--portal-text-panel: 1.25rem;
|
|
119
|
-
--portal-text-heading: 1.5rem;
|
|
120
|
-
--portal-text-title-sm: 1.875rem;
|
|
121
|
-
--portal-text-title: clamp(1.75rem, 1.6rem + 0.7vw, 2rem);
|
|
122
|
-
--portal-text-metric: 2.75rem;
|
|
123
|
-
--portal-text-metric-lg: 3.5rem;
|
|
124
219
|
--type-paragraph-large: 1.09375rem;
|
|
220
|
+
--type-heading-2: clamp(2rem, 4vw, 2.8125rem);
|
|
221
|
+
--type-paragraph: 1rem;
|
|
125
222
|
--type-paragraph-small: 0.875rem;
|
|
126
223
|
--type-paragraph-mini: 0.75rem;
|
|
224
|
+
--type-label: 0.625rem;
|
|
127
225
|
|
|
128
226
|
--elevate-1: color-mix(in srgb, var(--foreground) 3%, transparent);
|
|
129
227
|
--elevate-2: color-mix(in srgb, var(--foreground) 5%, transparent);
|
|
@@ -141,6 +239,8 @@
|
|
|
141
239
|
--surface-button-soft: color-mix(in srgb, var(--foreground) 3.5%, var(--card));
|
|
142
240
|
--surface-button-soft-hover: color-mix(in srgb, var(--foreground) 7%, var(--card));
|
|
143
241
|
--border-button-soft-hover: color-mix(in srgb, var(--foreground) 16%, transparent);
|
|
242
|
+
--surface-button-brand: color-mix(in srgb, var(--brand-accent) 84%, var(--foreground));
|
|
243
|
+
--foreground-accent-link: color-mix(in srgb, var(--brand-accent) 45%, var(--foreground));
|
|
144
244
|
--surface-selection: color-mix(in srgb, var(--accent) 12%, var(--card));
|
|
145
245
|
--border-selection: color-mix(in srgb, var(--accent) 40%, var(--hairline));
|
|
146
246
|
--surface-pagination-active: color-mix(in srgb, var(--accent) 10%, var(--card));
|
|
@@ -275,6 +375,12 @@
|
|
|
275
375
|
|
|
276
376
|
--badge-count-bg: var(--semantic-danger);
|
|
277
377
|
--badge-count-fg: var(--brand-white);
|
|
378
|
+
--sheet-edit-border: color-mix(in srgb, var(--accent) 24%, var(--border));
|
|
379
|
+
--sheet-edit-surface: color-mix(in srgb, var(--accent) 4%, var(--card));
|
|
380
|
+
--sheet-edit-header: color-mix(in srgb, var(--accent) 20%, var(--card));
|
|
381
|
+
--sheet-edit-control-border: color-mix(in srgb, var(--accent) 22%, var(--border));
|
|
382
|
+
--sheet-edit-control-ring: color-mix(in srgb, var(--accent) 22%, transparent);
|
|
383
|
+
--sheet-edit-header-surface: linear-gradient(135deg, color-mix(in srgb, var(--accent) 16%, transparent), transparent 62%);
|
|
278
384
|
--on-fill-danger: var(--brand-white);
|
|
279
385
|
--on-fill-warning: #3a2a05;
|
|
280
386
|
--on-fill-success: #06281e;
|
|
@@ -296,14 +402,43 @@
|
|
|
296
402
|
--project-surface-primary: var(--card);
|
|
297
403
|
--project-surface-secondary: color-mix(in srgb, var(--foreground) 2%, var(--card) 98%);
|
|
298
404
|
--project-surface-item: color-mix(in srgb, var(--card) 96%, transparent);
|
|
299
|
-
--project-surface-hero: color-mix(in srgb, var(--accent) 8%, var(--card) 92%);
|
|
300
|
-
--project-surface-hero-border: color-mix(in srgb, var(--accent) 26%, var(--foreground) 8%);
|
|
301
405
|
--project-hero-surface: var(--brand-panel-surface);
|
|
302
406
|
--project-hero-surface-raised: var(--brand-panel-surface-raised);
|
|
303
407
|
--project-hero-foreground: var(--brand-panel-foreground);
|
|
304
408
|
--project-hero-muted: var(--brand-panel-muted);
|
|
305
409
|
--project-hero-subtle: var(--brand-panel-subtle);
|
|
306
410
|
--project-hero-border: var(--brand-panel-border);
|
|
411
|
+
--project-hero-base: var(--brand-surface-dark);
|
|
412
|
+
--project-hero-shadow: var(--brand-shadow-soft);
|
|
413
|
+
--dashboard-shadow-sm: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent);
|
|
414
|
+
--dashboard-shadow-md: 0 8px 24px color-mix(in srgb, var(--foreground) 8%, transparent);
|
|
415
|
+
--dashboard-shadow-lg: 0 10px 30px color-mix(in srgb, var(--foreground) 8%, transparent);
|
|
416
|
+
--dashboard-hero-glow: radial-gradient(circle, color-mix(in srgb, var(--accent) 38%, transparent), transparent 70%);
|
|
417
|
+
--dashboard-hero-highlight: linear-gradient(90deg, transparent, color-mix(in srgb, var(--accent) 60%, transparent), transparent);
|
|
418
|
+
--dashboard-tab-hover: color-mix(in srgb, var(--foreground) 7%, transparent);
|
|
419
|
+
--dashboard-tab-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 45%, transparent);
|
|
420
|
+
--dashboard-breakdown-track: color-mix(in srgb, var(--foreground) 7%, transparent);
|
|
421
|
+
--dashboard-accent-soft: color-mix(in srgb, var(--accent) 16%, transparent);
|
|
422
|
+
--dashboard-neutral-rule: color-mix(in srgb, var(--foreground) 14%, transparent);
|
|
423
|
+
--dashboard-task-risk-bg: color-mix(in srgb, var(--project-risk-overdue) 11%, transparent);
|
|
424
|
+
--dashboard-task-risk-hover: color-mix(in srgb, var(--project-risk-overdue) 16%, transparent);
|
|
425
|
+
--dashboard-task-due-bg: color-mix(in srgb, var(--project-risk-at-risk) 13%, transparent);
|
|
426
|
+
--dashboard-task-due-hover: color-mix(in srgb, var(--project-risk-at-risk) 18%, transparent);
|
|
427
|
+
--dashboard-task-flight-bg: color-mix(in srgb, var(--foreground) 5%, transparent);
|
|
428
|
+
--dashboard-task-flight-hover: color-mix(in srgb, var(--foreground) 7%, transparent);
|
|
429
|
+
--dashboard-task-row-hover: color-mix(in srgb, var(--accent) 6%, transparent);
|
|
430
|
+
--dashboard-milestone-glow: radial-gradient(circle, color-mix(in srgb, var(--accent) 30%, transparent), transparent 70%);
|
|
431
|
+
--dashboard-milestone-icon: color-mix(in srgb, var(--accent) 18%, transparent);
|
|
432
|
+
--dashboard-milestone-skeleton: color-mix(in srgb, var(--project-hero-foreground) 12%, transparent);
|
|
433
|
+
--dashboard-milestone-empty: color-mix(in srgb, var(--project-hero-foreground) 10%, transparent);
|
|
434
|
+
--dashboard-milestone-date: color-mix(in srgb, var(--project-hero-foreground) 8%, transparent);
|
|
435
|
+
--dashboard-period-glow: color-mix(in srgb, var(--accent) 22%, transparent);
|
|
436
|
+
--dashboard-client-avatar: color-mix(in srgb, var(--role-client) 18%, var(--card));
|
|
437
|
+
--dashboard-local-muted-foreground: color-mix(in srgb, var(--foreground) 62%, transparent);
|
|
438
|
+
--dashboard-local-border: color-mix(in srgb, var(--foreground) 14%, transparent);
|
|
439
|
+
--dashboard-local-muted: color-mix(in srgb, var(--foreground) 6%, transparent);
|
|
440
|
+
--dashboard-danger-soft: color-mix(in srgb, var(--project-risk-overdue) 15%, transparent);
|
|
441
|
+
--dashboard-danger-border: color-mix(in srgb, var(--project-risk-overdue) 40%, transparent);
|
|
307
442
|
--project-surface-padding: 1.25rem;
|
|
308
443
|
--row-sweep-tint: var(--foreground);
|
|
309
444
|
--surface-card: color-mix(in srgb, var(--foreground) 2%, var(--card) 98%);
|
|
@@ -363,6 +498,7 @@
|
|
|
363
498
|
--secondary-foreground: #dce5f0;
|
|
364
499
|
--muted: rgba(148, 163, 184, 0.16);
|
|
365
500
|
--muted-foreground: #a6b4c6;
|
|
501
|
+
--foreground-muted-accessible: #a6b4c6;
|
|
366
502
|
--foreground-inverse: #f8fafc;
|
|
367
503
|
--foreground-inverse-muted: rgba(248, 250, 252, 0.9);
|
|
368
504
|
--foreground-inverse-subtle: rgba(248, 250, 252, 0.84);
|
|
@@ -388,6 +524,19 @@
|
|
|
388
524
|
--semantic-neutral: #a1a1aa;
|
|
389
525
|
--semantic-neutral-strong: #d4d4d8;
|
|
390
526
|
|
|
527
|
+
--project-risk-overdue-soft: var(--semantic-danger-soft);
|
|
528
|
+
/* Dark-mode health fills are light pastels, so on-fill ink stays dark. */
|
|
529
|
+
--project-risk-overdue-ink: #350a11;
|
|
530
|
+
--project-risk-at-risk-ink: #3a2a05;
|
|
531
|
+
--project-state-completed-ink: #06281e;
|
|
532
|
+
--project-health-on-track: var(--project-state-active-strong);
|
|
533
|
+
--project-health-at-risk: var(--project-risk-at-risk);
|
|
534
|
+
--project-health-at-risk-strong: var(--project-risk-at-risk-strong);
|
|
535
|
+
--project-health-off-track: var(--project-risk-overdue);
|
|
536
|
+
--project-health-progress: var(--project-state-active);
|
|
537
|
+
--project-health-off-track-strong: var(--project-risk-overdue);
|
|
538
|
+
--project-health-off-track-soft: var(--project-risk-overdue-soft);
|
|
539
|
+
|
|
391
540
|
--skeleton: color-mix(in srgb, var(--foreground) 9%, transparent);
|
|
392
541
|
--skeleton-strong: color-mix(in srgb, var(--foreground) 14%, transparent);
|
|
393
542
|
--skeleton-highlight: color-mix(in srgb, var(--brand-white) 12%, transparent);
|
|
@@ -449,6 +598,7 @@
|
|
|
449
598
|
--secondary-foreground: var(--brand-ink);
|
|
450
599
|
--muted: rgba(203, 213, 225, 0.25);
|
|
451
600
|
--muted-foreground: var(--brand-neutral-500);
|
|
601
|
+
--foreground-muted-accessible: #5f6b7a;
|
|
452
602
|
--foreground-inverse: var(--brand-white);
|
|
453
603
|
--foreground-inverse-muted: rgba(255, 255, 255, 0.88);
|
|
454
604
|
--foreground-inverse-subtle: rgba(255, 255, 255, 0.84);
|
package/src/typography.css
CHANGED
|
@@ -1,35 +1,24 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
--font-weight-regular: 400;
|
|
3
|
-
/* Mulish weight 500 is not loaded; medium deliberately resolves to 600. */
|
|
4
|
-
--font-weight-medium: 600;
|
|
5
|
-
--font-weight-bold: 700;
|
|
6
|
-
--font-weight-heavy: 800;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
1
|
@utility text-ui-micro {
|
|
10
|
-
font-family: var(--font-body)
|
|
2
|
+
font-family: var(--font-body);
|
|
11
3
|
font-size: var(--text-ui-micro);
|
|
12
4
|
font-weight: var(--font-weight-medium);
|
|
13
|
-
line-height:
|
|
14
|
-
color: var(--muted-foreground);
|
|
5
|
+
line-height: var(--type-leading-130);
|
|
15
6
|
}
|
|
16
7
|
|
|
17
8
|
@utility text-ui-label {
|
|
18
|
-
font-family: var(--font-body)
|
|
9
|
+
font-family: var(--font-body);
|
|
19
10
|
font-size: var(--text-ui-label);
|
|
20
11
|
font-weight: var(--font-weight-medium);
|
|
21
|
-
line-height:
|
|
12
|
+
line-height: var(--type-leading-none);
|
|
22
13
|
text-transform: uppercase;
|
|
23
|
-
letter-spacing:
|
|
24
|
-
color: var(--muted-foreground);
|
|
14
|
+
letter-spacing: var(--type-tracking-140);
|
|
25
15
|
}
|
|
26
16
|
|
|
27
17
|
@utility text-ui-meta {
|
|
28
|
-
font-family: var(--font-body)
|
|
18
|
+
font-family: var(--font-body);
|
|
29
19
|
font-size: var(--text-ui-meta);
|
|
30
20
|
font-weight: var(--font-weight-regular);
|
|
31
|
-
line-height:
|
|
32
|
-
color: var(--muted-foreground);
|
|
21
|
+
line-height: var(--type-leading-140);
|
|
33
22
|
}
|
|
34
23
|
|
|
35
24
|
/* Size-only utilities for component recipes that supply their own weight and rhythm. */
|
|
@@ -62,65 +51,58 @@
|
|
|
62
51
|
}
|
|
63
52
|
|
|
64
53
|
@utility text-ui-body {
|
|
65
|
-
font-family: var(--font-body)
|
|
54
|
+
font-family: var(--font-body);
|
|
66
55
|
font-size: var(--text-ui-body);
|
|
67
56
|
font-weight: var(--font-weight-regular);
|
|
68
|
-
line-height:
|
|
69
|
-
color: var(--foreground);
|
|
57
|
+
line-height: var(--type-leading-normal);
|
|
70
58
|
}
|
|
71
59
|
|
|
72
60
|
@utility text-ui-card-title {
|
|
73
|
-
font-family: var(--font-body)
|
|
61
|
+
font-family: var(--font-body);
|
|
74
62
|
font-size: var(--text-ui-card-title);
|
|
75
63
|
font-weight: var(--font-weight-medium);
|
|
76
|
-
line-height:
|
|
77
|
-
letter-spacing: -
|
|
78
|
-
color: var(--foreground);
|
|
64
|
+
line-height: var(--type-leading-130);
|
|
65
|
+
letter-spacing: var(--type-tracking-n025);
|
|
79
66
|
}
|
|
80
67
|
|
|
81
68
|
@utility text-ui-subhead {
|
|
82
|
-
font-family: var(--font-display)
|
|
69
|
+
font-family: var(--font-display);
|
|
83
70
|
font-size: var(--text-ui-subhead);
|
|
84
71
|
font-weight: var(--font-weight-bold);
|
|
85
|
-
line-height:
|
|
86
|
-
letter-spacing: -
|
|
87
|
-
color: var(--foreground);
|
|
72
|
+
line-height: var(--type-leading-tight);
|
|
73
|
+
letter-spacing: var(--type-tracking-n020);
|
|
88
74
|
}
|
|
89
75
|
|
|
90
76
|
@utility text-ui-panel-title {
|
|
91
|
-
font-family: var(--font-display)
|
|
77
|
+
font-family: var(--font-display);
|
|
92
78
|
font-size: var(--text-ui-panel-title);
|
|
93
79
|
font-weight: var(--font-weight-bold);
|
|
94
|
-
line-height:
|
|
95
|
-
letter-spacing: -
|
|
96
|
-
color: var(--foreground);
|
|
80
|
+
line-height: var(--type-leading-120);
|
|
81
|
+
letter-spacing: var(--type-tracking-n020);
|
|
97
82
|
}
|
|
98
83
|
|
|
99
84
|
@utility text-ui-heading {
|
|
100
|
-
font-family: var(--font-display)
|
|
85
|
+
font-family: var(--font-display);
|
|
101
86
|
font-size: var(--text-ui-heading);
|
|
102
87
|
font-weight: var(--font-weight-bold);
|
|
103
|
-
line-height:
|
|
104
|
-
letter-spacing: -
|
|
105
|
-
color: var(--foreground);
|
|
88
|
+
line-height: var(--type-leading-115);
|
|
89
|
+
letter-spacing: var(--type-tracking-n020);
|
|
106
90
|
}
|
|
107
91
|
|
|
108
92
|
@utility text-ui-title-sm {
|
|
109
|
-
font-family: var(--font-display)
|
|
93
|
+
font-family: var(--font-display);
|
|
110
94
|
font-size: var(--text-ui-title-sm);
|
|
111
95
|
font-weight: var(--font-weight-heavy);
|
|
112
|
-
line-height:
|
|
113
|
-
letter-spacing: -
|
|
114
|
-
color: var(--foreground);
|
|
96
|
+
line-height: var(--type-leading-110);
|
|
97
|
+
letter-spacing: var(--type-tracking-n030);
|
|
115
98
|
}
|
|
116
99
|
|
|
117
100
|
@utility text-ui-title {
|
|
118
|
-
font-family: var(--font-display)
|
|
101
|
+
font-family: var(--font-display);
|
|
119
102
|
font-size: var(--text-ui-title);
|
|
120
103
|
font-weight: var(--font-weight-heavy);
|
|
121
|
-
line-height:
|
|
122
|
-
letter-spacing: -
|
|
123
|
-
color: var(--foreground);
|
|
104
|
+
line-height: var(--type-leading-105);
|
|
105
|
+
letter-spacing: var(--type-tracking-n030);
|
|
124
106
|
}
|
|
125
107
|
|
|
126
108
|
@utility text-ui-metric {
|
|
@@ -128,29 +110,26 @@
|
|
|
128
110
|
font-variant-numeric: tabular-nums;
|
|
129
111
|
font-size: var(--text-ui-metric);
|
|
130
112
|
font-weight: var(--font-weight-heavy);
|
|
131
|
-
line-height:
|
|
132
|
-
letter-spacing: -
|
|
133
|
-
color: var(--foreground);
|
|
113
|
+
line-height: var(--type-leading-none);
|
|
114
|
+
letter-spacing: var(--type-tracking-n040);
|
|
134
115
|
}
|
|
135
116
|
|
|
136
117
|
@utility text-ui-metric-xl {
|
|
137
|
-
font-family: var(--font-display)
|
|
118
|
+
font-family: var(--font-display);
|
|
138
119
|
font-variant-numeric: tabular-nums;
|
|
139
120
|
font-size: var(--text-ui-metric-xl);
|
|
140
121
|
font-weight: var(--font-weight-heavy);
|
|
141
|
-
line-height:
|
|
142
|
-
letter-spacing: -
|
|
143
|
-
color: var(--foreground);
|
|
122
|
+
line-height: var(--type-leading-095);
|
|
123
|
+
letter-spacing: var(--type-tracking-n040);
|
|
144
124
|
}
|
|
145
125
|
|
|
146
126
|
@utility text-ui-metric-display {
|
|
147
|
-
font-family: var(--font-display)
|
|
127
|
+
font-family: var(--font-display);
|
|
148
128
|
font-variant-numeric: tabular-nums;
|
|
149
129
|
font-size: var(--text-ui-metric-display);
|
|
150
130
|
font-weight: var(--font-weight-heavy);
|
|
151
|
-
line-height:
|
|
152
|
-
letter-spacing: -
|
|
153
|
-
color: var(--foreground);
|
|
131
|
+
line-height: var(--type-leading-none);
|
|
132
|
+
letter-spacing: var(--type-tracking-n040);
|
|
154
133
|
}
|
|
155
134
|
|
|
156
135
|
/* Thin scrollbar for bounded surface lists. */
|
package/themes/mq-aliases.css
CHANGED
|
@@ -16,81 +16,91 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
@utility portal-micro {
|
|
19
|
-
font-family: var(--font-body)
|
|
19
|
+
font-family: var(--font-body);
|
|
20
20
|
font-size: var(--text-ui-micro);
|
|
21
21
|
font-weight: var(--font-weight-medium);
|
|
22
|
-
line-height:
|
|
22
|
+
line-height: var(--type-leading-130);
|
|
23
|
+
/* MQ parity: apps/portal/app/globals.css:718. */
|
|
23
24
|
color: var(--muted-foreground);
|
|
24
25
|
}
|
|
25
26
|
@utility portal-label {
|
|
26
|
-
font-family: var(--font-body)
|
|
27
|
+
font-family: var(--font-body);
|
|
27
28
|
font-size: var(--text-ui-label);
|
|
28
29
|
font-weight: var(--font-weight-medium);
|
|
29
|
-
line-height:
|
|
30
|
+
line-height: var(--type-leading-none);
|
|
30
31
|
text-transform: uppercase;
|
|
31
|
-
letter-spacing:
|
|
32
|
+
letter-spacing: var(--type-tracking-140);
|
|
33
|
+
/* MQ parity: apps/portal/app/globals.css:663. */
|
|
32
34
|
color: var(--muted-foreground);
|
|
33
35
|
}
|
|
34
36
|
@utility portal-meta {
|
|
35
|
-
font-family: var(--font-body)
|
|
37
|
+
font-family: var(--font-body);
|
|
36
38
|
font-size: var(--text-ui-meta);
|
|
37
39
|
font-weight: var(--font-weight-regular);
|
|
38
|
-
line-height:
|
|
40
|
+
line-height: var(--type-leading-140);
|
|
41
|
+
/* MQ parity: apps/portal/app/globals.css:711. */
|
|
39
42
|
color: var(--muted-foreground);
|
|
40
43
|
}
|
|
41
44
|
@utility portal-body {
|
|
42
|
-
font-family: var(--font-body)
|
|
45
|
+
font-family: var(--font-body);
|
|
43
46
|
font-size: var(--text-ui-body);
|
|
44
47
|
font-weight: var(--font-weight-regular);
|
|
45
|
-
line-height:
|
|
48
|
+
line-height: var(--type-leading-normal);
|
|
49
|
+
/* MQ parity: apps/portal/app/globals.css:705. */
|
|
46
50
|
color: var(--foreground);
|
|
47
51
|
}
|
|
48
52
|
@utility portal-card-title {
|
|
49
|
-
font-family: var(--font-body)
|
|
53
|
+
font-family: var(--font-body);
|
|
50
54
|
font-size: var(--text-ui-card-title);
|
|
51
55
|
font-weight: var(--font-weight-medium);
|
|
52
|
-
line-height:
|
|
53
|
-
letter-spacing: -
|
|
56
|
+
line-height: var(--type-leading-130);
|
|
57
|
+
letter-spacing: var(--type-tracking-n025);
|
|
58
|
+
/* MQ parity: apps/portal/app/globals.css:654. */
|
|
54
59
|
color: var(--foreground);
|
|
55
60
|
}
|
|
56
61
|
@utility portal-subhead {
|
|
57
|
-
font-family: var(--font-display)
|
|
62
|
+
font-family: var(--font-display);
|
|
58
63
|
font-size: var(--text-ui-subhead);
|
|
59
64
|
font-weight: var(--font-weight-bold);
|
|
60
|
-
line-height:
|
|
61
|
-
letter-spacing: -
|
|
65
|
+
line-height: var(--type-leading-tight);
|
|
66
|
+
letter-spacing: var(--type-tracking-n020);
|
|
67
|
+
/* MQ parity: apps/portal/app/globals.css:646. */
|
|
62
68
|
color: var(--foreground);
|
|
63
69
|
}
|
|
64
70
|
@utility portal-panel-title {
|
|
65
|
-
font-family: var(--font-display)
|
|
71
|
+
font-family: var(--font-display);
|
|
66
72
|
font-size: var(--text-ui-panel-title);
|
|
67
73
|
font-weight: var(--font-weight-bold);
|
|
68
|
-
line-height:
|
|
69
|
-
letter-spacing: -
|
|
74
|
+
line-height: var(--type-leading-120);
|
|
75
|
+
letter-spacing: var(--type-tracking-n020);
|
|
76
|
+
/* MQ parity: apps/portal/app/globals.css:636. */
|
|
70
77
|
color: var(--foreground);
|
|
71
78
|
}
|
|
72
79
|
@utility portal-heading {
|
|
73
|
-
font-family: var(--font-display)
|
|
80
|
+
font-family: var(--font-display);
|
|
74
81
|
font-size: var(--text-ui-heading);
|
|
75
82
|
font-weight: var(--font-weight-bold);
|
|
76
|
-
line-height:
|
|
77
|
-
letter-spacing: -
|
|
83
|
+
line-height: var(--type-leading-115);
|
|
84
|
+
letter-spacing: var(--type-tracking-n020);
|
|
85
|
+
/* MQ parity: apps/portal/app/globals.css:626. */
|
|
78
86
|
color: var(--foreground);
|
|
79
87
|
}
|
|
80
88
|
@utility portal-title-sm {
|
|
81
|
-
font-family: var(--font-display)
|
|
89
|
+
font-family: var(--font-display);
|
|
82
90
|
font-size: var(--text-ui-title-sm);
|
|
83
91
|
font-weight: var(--font-weight-heavy);
|
|
84
|
-
line-height:
|
|
85
|
-
letter-spacing: -
|
|
92
|
+
line-height: var(--type-leading-110);
|
|
93
|
+
letter-spacing: var(--type-tracking-n030);
|
|
94
|
+
/* MQ parity: apps/portal/app/globals.css:617. */
|
|
86
95
|
color: var(--foreground);
|
|
87
96
|
}
|
|
88
97
|
@utility portal-title {
|
|
89
|
-
font-family: var(--font-display)
|
|
98
|
+
font-family: var(--font-display);
|
|
90
99
|
font-size: var(--text-ui-title);
|
|
91
100
|
font-weight: var(--font-weight-heavy);
|
|
92
|
-
line-height:
|
|
93
|
-
letter-spacing: -
|
|
101
|
+
line-height: var(--type-leading-105);
|
|
102
|
+
letter-spacing: var(--type-tracking-n030);
|
|
103
|
+
/* MQ parity: apps/portal/app/globals.css:606. */
|
|
94
104
|
color: var(--foreground);
|
|
95
105
|
}
|
|
96
106
|
@utility portal-metric {
|
|
@@ -98,26 +108,29 @@
|
|
|
98
108
|
font-variant-numeric: tabular-nums;
|
|
99
109
|
font-size: var(--text-ui-metric);
|
|
100
110
|
font-weight: var(--font-weight-heavy);
|
|
101
|
-
line-height:
|
|
102
|
-
letter-spacing: -
|
|
111
|
+
line-height: var(--type-leading-none);
|
|
112
|
+
letter-spacing: var(--type-tracking-n040);
|
|
113
|
+
/* MQ parity: apps/portal/app/globals.css:673. */
|
|
103
114
|
color: var(--foreground);
|
|
104
115
|
}
|
|
105
116
|
@utility portal-metric-xl {
|
|
106
|
-
font-family: var(--font-display)
|
|
117
|
+
font-family: var(--font-display);
|
|
107
118
|
font-variant-numeric: tabular-nums;
|
|
108
119
|
font-size: var(--text-ui-metric-xl);
|
|
109
120
|
font-weight: var(--font-weight-heavy);
|
|
110
|
-
line-height:
|
|
111
|
-
letter-spacing: -
|
|
121
|
+
line-height: var(--type-leading-095);
|
|
122
|
+
letter-spacing: var(--type-tracking-n040);
|
|
123
|
+
/* MQ parity: apps/portal/app/globals.css:697. */
|
|
112
124
|
color: var(--foreground);
|
|
113
125
|
}
|
|
114
126
|
@utility portal-metric-display {
|
|
115
|
-
font-family: var(--font-display)
|
|
127
|
+
font-family: var(--font-display);
|
|
116
128
|
font-variant-numeric: tabular-nums;
|
|
117
129
|
font-size: var(--text-ui-metric-display);
|
|
118
130
|
font-weight: var(--font-weight-heavy);
|
|
119
|
-
line-height:
|
|
120
|
-
letter-spacing: -
|
|
131
|
+
line-height: var(--type-leading-none);
|
|
132
|
+
letter-spacing: var(--type-tracking-n040);
|
|
133
|
+
/* MQ parity: apps/portal/app/globals.css:685. */
|
|
121
134
|
color: var(--foreground);
|
|
122
135
|
}
|
|
123
136
|
@utility portal-scroll {
|
|
@@ -138,25 +151,54 @@
|
|
|
138
151
|
}
|
|
139
152
|
}
|
|
140
153
|
|
|
141
|
-
|
|
142
|
-
.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
154
|
+
@layer components {
|
|
155
|
+
.heading-2 {
|
|
156
|
+
margin: 0;
|
|
157
|
+
font-family: var(--font-display);
|
|
158
|
+
font-size: var(--type-heading-2);
|
|
159
|
+
font-weight: var(--font-weight-black);
|
|
160
|
+
line-height: var(--type-leading-110);
|
|
161
|
+
letter-spacing: var(--type-tracking-n025);
|
|
162
|
+
text-wrap: balance;
|
|
163
|
+
}
|
|
148
164
|
|
|
149
|
-
.paragraph
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
165
|
+
.paragraph,
|
|
166
|
+
.paragraph-large,
|
|
167
|
+
.paragraph-small,
|
|
168
|
+
.paragraph-mini {
|
|
169
|
+
margin: 0;
|
|
170
|
+
font-family: var(--font-body);
|
|
171
|
+
font-weight: var(--font-weight-regular);
|
|
172
|
+
letter-spacing: var(--type-tracking-010);
|
|
173
|
+
}
|
|
153
174
|
|
|
154
|
-
.paragraph
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
175
|
+
.paragraph {
|
|
176
|
+
font-size: var(--type-paragraph);
|
|
177
|
+
line-height: var(--type-leading-172);
|
|
178
|
+
}
|
|
158
179
|
|
|
159
|
-
.paragraph-
|
|
160
|
-
|
|
161
|
-
|
|
180
|
+
.paragraph-large {
|
|
181
|
+
font-size: var(--type-paragraph-large);
|
|
182
|
+
line-height: var(--type-leading-155);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.paragraph-small {
|
|
186
|
+
font-size: var(--type-paragraph-small);
|
|
187
|
+
line-height: var(--type-leading-normal);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.paragraph-mini {
|
|
191
|
+
font-size: var(--type-paragraph-mini);
|
|
192
|
+
line-height: var(--type-leading-145);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.label {
|
|
196
|
+
margin: 0;
|
|
197
|
+
font-family: var(--font-display);
|
|
198
|
+
font-size: var(--type-label);
|
|
199
|
+
font-weight: var(--font-weight-heavy);
|
|
200
|
+
line-height: var(--type-leading-120);
|
|
201
|
+
letter-spacing: var(--type-tracking-120);
|
|
202
|
+
text-transform: uppercase;
|
|
203
|
+
}
|
|
162
204
|
}
|
package/themes/mq.css
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* MQ compatibility palette. Import after @brightweblabs/theme/css. */
|
|
2
2
|
:root {
|
|
3
|
+
/* MQ deployments load their client font at the app root and restore it with
|
|
4
|
+
one theme override: --font-body: var(--font-client-body); */
|
|
3
5
|
--brand-accent: #5bc5f2;
|
|
4
6
|
--brand-accent-soft: #6fc4e7;
|
|
5
7
|
--brand-ink: #0a151a;
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
--secondary-foreground: var(--brand-ink);
|
|
27
29
|
--muted: rgba(191, 192, 207, 0.18);
|
|
28
30
|
--muted-foreground: var(--brand-neutral-500);
|
|
31
|
+
--foreground-muted-accessible: #606570;
|
|
29
32
|
--foreground-inverse: var(--brand-white);
|
|
30
33
|
--foreground-inverse-muted: rgba(255, 255, 255, 0.88);
|
|
31
34
|
--foreground-inverse-subtle: rgba(255, 255, 255, 0.84);
|
|
@@ -59,17 +62,34 @@
|
|
|
59
62
|
--brand-panel-muted: rgba(246, 251, 255, 0.66);
|
|
60
63
|
--brand-panel-subtle: rgba(246, 251, 255, 0.46);
|
|
61
64
|
--brand-panel-border: rgba(145, 211, 241, 0.2);
|
|
65
|
+
--auth-wash: radial-gradient(circle at 50% 0%, color-mix(in srgb, var(--brand-accent) 11%, transparent), transparent 54%);
|
|
66
|
+
--auth-card-surface: color-mix(in srgb, var(--card) 96%, transparent);
|
|
67
|
+
--auth-card-border: color-mix(in srgb, var(--brand-accent) 18%, var(--border));
|
|
68
|
+
--auth-card-shadow: var(--brand-shadow-soft);
|
|
69
|
+
--auth-card-radius: var(--radius-panel);
|
|
70
|
+
--auth-panel-surface: var(--brand-panel-surface);
|
|
71
|
+
--auth-panel-foreground: var(--brand-panel-foreground);
|
|
72
|
+
--auth-panel-muted: var(--brand-panel-muted);
|
|
73
|
+
--auth-panel-border: var(--brand-panel-border);
|
|
74
|
+
--auth-success-surface: var(--surface-status-success);
|
|
75
|
+
--auth-success-border: color-mix(in srgb, var(--semantic-success) 30%, transparent);
|
|
76
|
+
--auth-success-foreground: var(--semantic-success-strong);
|
|
77
|
+
--auth-error-surface: var(--surface-danger-subtle);
|
|
78
|
+
--auth-error-border: color-mix(in srgb, var(--destructive) 28%, transparent);
|
|
79
|
+
--auth-error-foreground: var(--destructive);
|
|
80
|
+
--auth-skeleton-surface: var(--elevate-2);
|
|
81
|
+
--auth-skeleton-highlight: color-mix(in srgb, var(--card) 72%, transparent);
|
|
62
82
|
--project-surface-primary: var(--card);
|
|
63
83
|
--project-surface-secondary: color-mix(in srgb, var(--foreground) 2%, var(--card) 98%);
|
|
64
84
|
--project-surface-item: color-mix(in srgb, var(--card) 96%, transparent);
|
|
65
|
-
--project-surface-hero: color-mix(in srgb, var(--accent) 8%, var(--card) 92%);
|
|
66
|
-
--project-surface-hero-border: color-mix(in srgb, var(--accent) 26%, var(--foreground) 8%);
|
|
67
85
|
--project-hero-surface: linear-gradient(158deg, #02070d 0%, #06111c 30%, #071d2b 63%, #123747 100%);
|
|
68
86
|
--project-hero-surface-raised: #0b2634;
|
|
69
87
|
--project-hero-foreground: #f6fbff;
|
|
70
88
|
--project-hero-muted: rgba(246, 251, 255, 0.66);
|
|
71
89
|
--project-hero-subtle: rgba(246, 251, 255, 0.46);
|
|
72
90
|
--project-hero-border: rgba(145, 211, 241, 0.2);
|
|
91
|
+
--project-hero-base: #061827;
|
|
92
|
+
--project-hero-shadow: 0 18px 50px rgba(6, 29, 51, 0.14);
|
|
73
93
|
--project-surface-padding: 1.25rem;
|
|
74
94
|
}
|
|
75
95
|
|
|
@@ -102,6 +122,7 @@
|
|
|
102
122
|
--secondary-foreground: #dceaf7;
|
|
103
123
|
--muted: rgba(132, 170, 198, 0.16);
|
|
104
124
|
--muted-foreground: #9eb6cd;
|
|
125
|
+
--foreground-muted-accessible: #9eb6cd;
|
|
105
126
|
--foreground-inverse: #f7fbff;
|
|
106
127
|
--foreground-inverse-muted: rgba(247, 251, 255, 0.9);
|
|
107
128
|
--foreground-inverse-subtle: rgba(247, 251, 255, 0.84);
|
|
@@ -152,14 +173,14 @@
|
|
|
152
173
|
--project-surface-primary: var(--card);
|
|
153
174
|
--project-surface-secondary: color-mix(in srgb, var(--foreground) 2%, var(--card) 98%);
|
|
154
175
|
--project-surface-item: color-mix(in srgb, var(--card) 96%, transparent);
|
|
155
|
-
--project-surface-hero: color-mix(in srgb, var(--accent) 8%, var(--card) 92%);
|
|
156
|
-
--project-surface-hero-border: color-mix(in srgb, var(--accent) 26%, var(--foreground) 8%);
|
|
157
176
|
--project-hero-surface: linear-gradient(158deg, #0c2433 0%, #143b4e 52%, #1b4f66 100%);
|
|
158
177
|
--project-hero-surface-raised: #0b2634;
|
|
159
178
|
--project-hero-foreground: #f6fbff;
|
|
160
179
|
--project-hero-muted: rgba(246, 251, 255, 0.66);
|
|
161
180
|
--project-hero-subtle: rgba(246, 251, 255, 0.46);
|
|
162
181
|
--project-hero-border: color-mix(in srgb, var(--accent) 20%, transparent);
|
|
182
|
+
--project-hero-base: #0c2433;
|
|
183
|
+
--project-hero-shadow: 0 18px 50px rgba(0, 0, 0, 0.32);
|
|
163
184
|
}
|
|
164
185
|
|
|
165
186
|
:root.light,
|
|
@@ -190,6 +211,7 @@
|
|
|
190
211
|
--secondary-foreground: var(--brand-ink);
|
|
191
212
|
--muted: rgba(191, 192, 207, 0.18);
|
|
192
213
|
--muted-foreground: var(--brand-neutral-500);
|
|
214
|
+
--foreground-muted-accessible: #606570;
|
|
193
215
|
--accent: var(--brand-accent);
|
|
194
216
|
--accent-foreground: var(--brand-ink);
|
|
195
217
|
--destructive: #b43f3f;
|
|
@@ -206,4 +228,6 @@
|
|
|
206
228
|
--project-hero-muted: rgba(246, 251, 255, 0.66);
|
|
207
229
|
--project-hero-subtle: rgba(246, 251, 255, 0.46);
|
|
208
230
|
--project-hero-border: rgba(145, 211, 241, 0.2);
|
|
231
|
+
--project-hero-base: #061827;
|
|
232
|
+
--project-hero-shadow: 0 18px 50px rgba(6, 29, 51, 0.14);
|
|
209
233
|
}
|