@brightweblabs/theme 0.2.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/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@brightweblabs/theme",
3
+ "private": false,
4
+ "version": "0.2.0",
5
+ "main": "./src/tint.ts",
6
+ "types": "./src/tint.ts",
7
+ "files": [
8
+ "src",
9
+ "themes"
10
+ ],
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/BWLeoRibeiro/brightweb-platform.git"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "exports": {
20
+ ".": "./src/tint.ts",
21
+ "./css": "./src/index.css",
22
+ "./tint": "./src/tint.ts",
23
+ "./themes/mq": "./themes/mq.css",
24
+ "./themes/mq-aliases": "./themes/mq-aliases.css"
25
+ }
26
+ }
package/src/base.css ADDED
@@ -0,0 +1,33 @@
1
+ /* Keep the reset layered so Tailwind utilities and component variants retain
2
+ precedence over these element defaults. */
3
+ @layer base {
4
+ *,
5
+ ::before,
6
+ ::after {
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ html,
11
+ body {
12
+ margin: 0;
13
+ padding: 0;
14
+ background: var(--page-background);
15
+ color: var(--foreground);
16
+ font-family: var(--font-sans), sans-serif;
17
+ -webkit-font-smoothing: antialiased;
18
+ -moz-osx-font-smoothing: grayscale;
19
+ text-rendering: optimizeLegibility;
20
+ }
21
+
22
+ a {
23
+ color: inherit;
24
+ text-decoration: none;
25
+ }
26
+
27
+ /* Unlayered, this shorthand beats @layer utilities and erases button
28
+ variant typography. */
29
+ button,
30
+ input {
31
+ font: inherit;
32
+ }
33
+ }
package/src/index.css ADDED
@@ -0,0 +1,5 @@
1
+ @import "./tokens.css";
2
+ @import "./theme.css";
3
+ @import "./typography.css";
4
+ @import "./base.css";
5
+ @import "./surfaces.css";
@@ -0,0 +1,175 @@
1
+ /* ── Shared structural surfaces ───────────────────────────────────────── */
2
+ .surface-card {
3
+ border-radius: var(--radius-card);
4
+ border: 1px solid var(--border-hairline);
5
+ background: var(--surface-card);
6
+ padding: var(--surface-card-padding);
7
+ animation: surface-fade-in 640ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
8
+ }
9
+
10
+ .surface-card.is-light {
11
+ background: var(--surface-card-light);
12
+ }
13
+
14
+ /* A near-black panel has strong figure/ground in light mode. In dark mode it
15
+ elevates above the page through a lighter accent mix, border, and shadow. */
16
+ .brand-panel {
17
+ --row-sweep-tint: var(--brand-panel-foreground);
18
+ background: var(--brand-panel-surface);
19
+ }
20
+
21
+ .dark .brand-panel,
22
+ .theme-dark .brand-panel {
23
+ border: 1px solid var(--brand-panel-border);
24
+ box-shadow: var(--brand-shadow-lift);
25
+ }
26
+
27
+ .row-hover-sweep {
28
+ pointer-events: none;
29
+ position: absolute;
30
+ inset: 0;
31
+ border-radius: var(--radius-card);
32
+ opacity: 0;
33
+ transition: opacity 300ms ease;
34
+ background: linear-gradient(
35
+ 90deg,
36
+ transparent,
37
+ color-mix(in srgb, var(--row-sweep-tint, var(--foreground)) 9%, transparent) 50%,
38
+ transparent
39
+ );
40
+ }
41
+
42
+ .group:hover > .row-hover-sweep,
43
+ .group:focus-visible > .row-hover-sweep {
44
+ opacity: 1;
45
+ }
46
+
47
+ /* ── Canonical tinted-pill recipes ────────────────────────────────────── */
48
+ @layer components {
49
+ .tint-soft {
50
+ border-color: color-mix(in srgb, var(--tint) 34%, transparent);
51
+ background-color: color-mix(in srgb, var(--tint) 10%, var(--card));
52
+ color: var(--tint-strong);
53
+ }
54
+
55
+ .tint-soft:hover {
56
+ background-color: color-mix(in srgb, var(--tint) 14%, var(--card));
57
+ }
58
+
59
+ .tint-hero {
60
+ border-color: color-mix(in srgb, var(--tint) 46%, transparent);
61
+ background-color: color-mix(in srgb, var(--tint) 16%, transparent);
62
+ color: color-mix(in srgb, var(--tint) 18%, white);
63
+ }
64
+
65
+ .tint-hero:hover {
66
+ background-color: color-mix(in srgb, var(--tint) 24%, transparent);
67
+ }
68
+ }
69
+
70
+ .section-icon {
71
+ display: flex;
72
+ width: 1.875rem;
73
+ height: 1.875rem;
74
+ flex-shrink: 0;
75
+ align-items: center;
76
+ justify-content: center;
77
+ border-radius: 999px;
78
+ background: var(--muted);
79
+ color: var(--muted-foreground);
80
+ }
81
+
82
+ .stat-cell {
83
+ padding: var(--stat-cell-padding);
84
+ }
85
+
86
+ /* Skeleton shimmer respects reduced-motion with a quiet breathe fallback. */
87
+ @keyframes surface-fade-in {
88
+ from {
89
+ opacity: 0;
90
+ transform: translateY(10px);
91
+ }
92
+ to {
93
+ opacity: 1;
94
+ transform: translateY(0);
95
+ }
96
+ }
97
+
98
+ @keyframes skeleton-shimmer {
99
+ 100% {
100
+ transform: translateX(100%);
101
+ }
102
+ }
103
+
104
+ @keyframes skeleton-breathe {
105
+ 0%,
106
+ 100% {
107
+ opacity: 1;
108
+ }
109
+ 50% {
110
+ opacity: 0.6;
111
+ }
112
+ }
113
+
114
+ .skeleton-ghost {
115
+ position: relative;
116
+ overflow: hidden;
117
+ background: var(--skeleton);
118
+ }
119
+
120
+ .skeleton-ghost::after {
121
+ content: "";
122
+ position: absolute;
123
+ inset: 0;
124
+ transform: translateX(-100%);
125
+ background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent);
126
+ animation: skeleton-shimmer 1.6s ease-in-out infinite;
127
+ }
128
+
129
+ @media (prefers-reduced-motion: reduce) {
130
+ .skeleton-ghost::after {
131
+ display: none;
132
+ }
133
+
134
+ .skeleton-ghost {
135
+ animation: skeleton-breathe 2.4s ease-in-out infinite;
136
+ }
137
+ }
138
+
139
+ .eyebrow {
140
+ display: inline-flex;
141
+ width: fit-content;
142
+ padding: 6px 10px;
143
+ border-radius: 999px;
144
+ background: var(--brand-surface-tint);
145
+ color: var(--brand-accent);
146
+ font-size: var(--text-ui-label);
147
+ font-weight: var(--font-weight-bold);
148
+ letter-spacing: 0.04em;
149
+ text-transform: uppercase;
150
+ }
151
+
152
+ .status {
153
+ display: inline-flex;
154
+ align-items: center;
155
+ gap: 8px;
156
+ padding: 8px 12px;
157
+ border-radius: 999px;
158
+ font-size: var(--text-ui-meta);
159
+ font-weight: var(--font-weight-bold);
160
+ }
161
+
162
+ .status.ok {
163
+ background: color-mix(in srgb, var(--semantic-success) 14%, transparent);
164
+ color: var(--semantic-success-strong);
165
+ }
166
+
167
+ .status.warn {
168
+ background: color-mix(in srgb, var(--semantic-warning) 14%, transparent);
169
+ color: var(--semantic-warning-strong);
170
+ }
171
+
172
+ .status.error {
173
+ background: color-mix(in srgb, var(--semantic-danger) 12%, transparent);
174
+ color: var(--semantic-danger-strong);
175
+ }
package/src/theme.css ADDED
@@ -0,0 +1,120 @@
1
+ @theme inline {
2
+ /* L1: shadcn semantics. */
3
+ --color-background: var(--background);
4
+ --color-foreground: var(--foreground);
5
+ --color-card: var(--card);
6
+ --color-card-foreground: var(--card-foreground);
7
+ --color-popover: var(--popover);
8
+ --color-popover-foreground: var(--popover-foreground);
9
+ --color-primary: var(--primary);
10
+ --color-primary-foreground: var(--primary-foreground);
11
+ --color-secondary: var(--secondary);
12
+ --color-secondary-foreground: var(--secondary-foreground);
13
+ --color-muted: var(--muted);
14
+ --color-muted-foreground: var(--muted-foreground);
15
+ --color-accent: var(--accent);
16
+ --color-accent-foreground: var(--accent-foreground);
17
+ --color-destructive: var(--destructive);
18
+ --color-destructive-foreground: var(--destructive-foreground);
19
+ --color-border: var(--border);
20
+ --color-input: var(--input);
21
+ --color-ring: var(--ring);
22
+ --color-foreground-inverse: var(--foreground-inverse);
23
+ --color-foreground-inverse-muted: var(--foreground-inverse-muted);
24
+ --color-foreground-inverse-subtle: var(--foreground-inverse-subtle);
25
+
26
+ /* L2: status hues. */
27
+ --color-semantic-info: var(--semantic-info);
28
+ --color-semantic-info-strong: var(--semantic-info-strong);
29
+ --color-semantic-special: var(--semantic-special);
30
+ --color-semantic-special-strong: var(--semantic-special-strong);
31
+ --color-semantic-warning: var(--semantic-warning);
32
+ --color-semantic-warning-strong: var(--semantic-warning-strong);
33
+ --color-semantic-success: var(--semantic-success);
34
+ --color-semantic-success-strong: var(--semantic-success-strong);
35
+ --color-semantic-danger: var(--semantic-danger);
36
+ --color-semantic-danger-strong: var(--semantic-danger-strong);
37
+ --color-semantic-danger-soft: var(--semantic-danger-soft);
38
+ --color-semantic-neutral: var(--semantic-neutral);
39
+ --color-semantic-neutral-strong: var(--semantic-neutral-strong);
40
+
41
+ /* L3: recipes, elevation, roles, and on-fill inks. */
42
+ --color-border-hairline: var(--border-hairline);
43
+ --color-border-hairline-soft: var(--border-hairline-soft);
44
+ --color-border-strong: var(--border-strong);
45
+ --color-surface-hover: var(--surface-hover);
46
+ --color-skeleton: var(--skeleton);
47
+ --color-skeleton-strong: var(--skeleton-strong);
48
+ --color-skeleton-highlight: var(--skeleton-highlight);
49
+ --color-elevate-1: var(--elevate-1);
50
+ --color-elevate-2: var(--elevate-2);
51
+ --color-elevate-3: var(--elevate-3);
52
+ --color-hairline: var(--hairline);
53
+ --color-hairline-strong: var(--hairline-strong);
54
+ --color-role-client: var(--role-client);
55
+ --color-role-client-strong: var(--role-client-strong);
56
+ --color-role-team: var(--role-team);
57
+ --color-role-team-strong: var(--role-team-strong);
58
+ --color-role-admin: var(--role-admin);
59
+ --color-role-admin-strong: var(--role-admin-strong);
60
+ --color-role-manager: var(--role-manager);
61
+ --color-role-manager-strong: var(--role-manager-strong);
62
+ --color-badge-count: var(--badge-count-bg);
63
+ --color-badge-count-foreground: var(--badge-count-fg);
64
+ --color-badge-count-bg: var(--badge-count-bg);
65
+ --color-badge-count-fg: var(--badge-count-fg);
66
+ --color-on-fill-danger: var(--on-fill-danger);
67
+ --color-on-fill-warning: var(--on-fill-warning);
68
+ --color-on-fill-success: var(--on-fill-success);
69
+ --color-surface-card: var(--surface-card);
70
+ --color-surface-card-light: var(--surface-card-light);
71
+ --color-brand-panel-foreground: var(--brand-panel-foreground);
72
+ --color-brand-panel-muted: var(--brand-panel-muted);
73
+ --color-brand-panel-subtle: var(--brand-panel-subtle);
74
+ --color-brand-panel-border: var(--brand-panel-border);
75
+ --color-brand-panel-surface-raised: var(--brand-panel-surface-raised);
76
+ --color-row-sweep-tint: var(--row-sweep-tint);
77
+
78
+ /* Collapse Tailwind's radius scale onto the three UI tiers. */
79
+ --radius-sm: var(--radius);
80
+ --radius-md: var(--radius);
81
+ --radius-lg: var(--radius-card);
82
+ --radius-xl: var(--radius-card);
83
+ --radius-2xl: var(--radius-panel);
84
+ --radius-3xl: var(--radius-panel);
85
+
86
+ /* Named spacing keys sit alongside Tailwind's numeric scale. */
87
+ --spacing-2xs: var(--space-2xs);
88
+ --spacing-xs: var(--space-xs);
89
+ --spacing-sm: var(--space-sm);
90
+ --spacing-md: var(--space-md);
91
+ --spacing-lg: var(--space-lg);
92
+ --spacing-lg-plus: var(--space-lg-plus);
93
+ --spacing-xl: var(--space-xl);
94
+ --spacing-2xl: var(--space-2xl);
95
+ --spacing-3xl: var(--space-3xl);
96
+ --spacing-4xl: var(--space-4xl);
97
+ --spacing-control: var(--space-control);
98
+ --spacing-button-y: var(--space-button-y);
99
+ --spacing-button-x: var(--space-button-x);
100
+ --spacing-card-pad-x: var(--space-card-pad-x);
101
+ --spacing-card-pad-x-tight: var(--space-card-pad-x-tight);
102
+ --spacing-copy-bottom: var(--space-copy-bottom);
103
+ --spacing-badge-y: var(--space-badge-y);
104
+ --spacing-badge-x: var(--space-badge-x);
105
+
106
+ /* Tailwind v4 uses --container-* for max-w-*. Keep spacing names from
107
+ shadowing the standard container widths. */
108
+ --container-2xs: 18rem;
109
+ --container-xs: 20rem;
110
+ --container-sm: 24rem;
111
+ --container-md: 28rem;
112
+ --container-lg: 32rem;
113
+ --container-xl: 36rem;
114
+ --container-2xl: 42rem;
115
+ --container-3xl: 48rem;
116
+ --container-4xl: 56rem;
117
+ --container-5xl: 64rem;
118
+ --container-6xl: 72rem;
119
+ --container-7xl: 80rem;
120
+ }
package/src/tint.ts ADDED
@@ -0,0 +1,22 @@
1
+ /** The two canonical tint recipes provided by the theme CSS. */
2
+ export type TintVariant = "soft" | "hero";
3
+
4
+ export type TintPillResult = {
5
+ className: "tint-soft" | "tint-hero";
6
+ style: Record<string, string>;
7
+ };
8
+
9
+ /**
10
+ * Pairs a semantic custom property with the canonical tinted-pill recipes.
11
+ * Pass the custom-property name without a var() wrapper.
12
+ */
13
+ export function tintPill(token: string, variant: TintVariant = "soft"): TintPillResult {
14
+ const style: Record<string, string> = { "--tint": `var(${token})` };
15
+
16
+ if (variant === "soft") {
17
+ style["--tint-strong"] = `var(${token}-strong)`;
18
+ return { className: "tint-soft", style };
19
+ }
20
+
21
+ return { className: "tint-hero", style };
22
+ }
package/src/tokens.css ADDED
@@ -0,0 +1,274 @@
1
+ /* ── L0: brand primitives ─────────────────────────────────────────────── */
2
+ :root {
3
+ color-scheme: light;
4
+ --font-body: "Mulish", "Mulish Fallback", "Segoe UI", Arial, sans-serif;
5
+ --font-heading: var(--font-body);
6
+ --font-sans: var(--font-body);
7
+ --font-display: var(--font-heading);
8
+ --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", "Menlo", monospace;
9
+
10
+ --brand-accent: #4a7dbd;
11
+ --brand-accent-soft: #7196c4;
12
+ --brand-ink: #111827;
13
+ --brand-neutral-500: #64748b;
14
+ --brand-neutral-300: #cbd5e1;
15
+ --brand-neutral-200: #e2e8f0;
16
+ --brand-neutral-100: #f1f5f9;
17
+ --brand-white: #ffffff;
18
+ --brand-border-subtle: rgba(15, 23, 42, 0.1);
19
+ --brand-surface-tint: rgba(74, 125, 189, 0.09);
20
+ --brand-surface-dark: rgba(15, 23, 42, 0.95);
21
+ --brand-shadow-soft: 0 20px 44px rgba(15, 23, 42, 0.1);
22
+ --brand-shadow-lift: 0 18px 32px rgba(15, 23, 42, 0.22);
23
+
24
+ /* ── L1: shadcn semantic contract ──────────────────────────────────── */
25
+ --background: var(--brand-white);
26
+ --foreground: var(--brand-ink);
27
+ --card: var(--brand-white);
28
+ --card-foreground: var(--brand-ink);
29
+ --popover: var(--brand-white);
30
+ --popover-foreground: var(--brand-ink);
31
+ --primary: var(--brand-ink);
32
+ --primary-foreground: var(--brand-white);
33
+ --secondary: var(--brand-neutral-100);
34
+ --secondary-foreground: var(--brand-ink);
35
+ --muted: rgba(203, 213, 225, 0.25);
36
+ --muted-foreground: var(--brand-neutral-500);
37
+ --foreground-inverse: var(--brand-white);
38
+ --foreground-inverse-muted: rgba(255, 255, 255, 0.88);
39
+ --foreground-inverse-subtle: rgba(255, 255, 255, 0.84);
40
+ --accent: var(--brand-accent);
41
+ --accent-foreground: var(--brand-white);
42
+ --destructive: #b43f3f;
43
+ --destructive-foreground: var(--brand-white);
44
+ --border: var(--brand-border-subtle);
45
+ --input: rgba(15, 23, 42, 0.09);
46
+ --ring: rgba(74, 125, 189, 0.42);
47
+
48
+ /* ── L2: brand-agnostic semantic colour base ───────────────────────── */
49
+ --semantic-info: #0ea5e9;
50
+ --semantic-info-strong: #0369a1;
51
+ --semantic-special: #8b5cf6;
52
+ --semantic-special-strong: #6d28d9;
53
+ --semantic-warning: #eab034;
54
+ --semantic-warning-strong: #7a5c15;
55
+ --semantic-success: #10b981;
56
+ --semantic-success-strong: #047857;
57
+ --semantic-danger: #c9373a;
58
+ --semantic-danger-strong: #b72f33;
59
+ --semantic-danger-soft: #e55759;
60
+ --semantic-neutral: #71717a;
61
+ --semantic-neutral-strong: #52525b;
62
+
63
+ /* ── L3: experience tokens ─────────────────────────────────────────── */
64
+ --space-2xs: 0.25rem;
65
+ --space-xs: 0.5rem;
66
+ --space-sm: 0.75rem;
67
+ --space-md: 1rem;
68
+ --space-lg: 1.5rem;
69
+ --space-lg-plus: 1.75rem;
70
+ --space-xl: 2rem;
71
+ --space-2xl: 2.5rem;
72
+ --space-3xl: 3rem;
73
+ --space-4xl: 3.75rem;
74
+ --space-control: 2.8rem;
75
+ --space-button-y: 1.15rem;
76
+ --space-button-x: 2.35rem;
77
+ --space-card-pad-x: 1.5rem;
78
+ --space-card-pad-x-tight: 1.25rem;
79
+ --space-copy-bottom: 2.25rem;
80
+ --space-badge-y: 0.4rem;
81
+ --space-badge-x: 0.7rem;
82
+
83
+ /* Controls, cards, and large panels. Full radius remains for pills/avatars. */
84
+ --radius: 0.3125rem;
85
+ --radius-control: 0.625rem;
86
+ --radius-card: 0.75rem;
87
+ --radius-panel: 1rem;
88
+
89
+ --text-ui-micro: 0.625rem;
90
+ --text-ui-label: 0.6875rem;
91
+ --text-ui-meta: 0.75rem;
92
+ --text-ui-body: 0.875rem;
93
+ --text-ui-card-title: 0.9375rem;
94
+ --text-ui-subhead: 1.125rem;
95
+ --text-ui-panel-title: 1.25rem;
96
+ --text-ui-heading: 1.5rem;
97
+ --text-ui-title-sm: 1.875rem;
98
+ --text-ui-title: clamp(1.75rem, 1.6rem + 0.7vw, 2rem);
99
+ --text-ui-metric: 2.75rem;
100
+ --text-ui-metric-xl: 3.5rem;
101
+ --text-ui-metric-display: var(--text-ui-metric);
102
+
103
+ --elevate-1: color-mix(in srgb, var(--foreground) 3%, transparent);
104
+ --elevate-2: color-mix(in srgb, var(--foreground) 5%, transparent);
105
+ --elevate-3: color-mix(in srgb, var(--foreground) 8%, transparent);
106
+ --hairline: color-mix(in srgb, var(--foreground) 8%, transparent);
107
+ --hairline-strong: color-mix(in srgb, var(--foreground) 12%, transparent);
108
+ --border-hairline: color-mix(in srgb, var(--foreground) 14%, transparent);
109
+ --border-hairline-soft: color-mix(in srgb, var(--foreground) 12%, transparent);
110
+ --border-strong: color-mix(in srgb, var(--foreground) 24%, transparent);
111
+ --surface-hover: color-mix(in srgb, var(--foreground) 4%, var(--card) 96%);
112
+
113
+ --skeleton: color-mix(in srgb, var(--foreground) 7%, transparent);
114
+ --skeleton-strong: color-mix(in srgb, var(--foreground) 11%, transparent);
115
+ --skeleton-highlight: color-mix(in srgb, var(--brand-white) 65%, transparent);
116
+
117
+ --role-client: #5076a8;
118
+ --role-client-strong: #31527f;
119
+ --role-team: #398579;
120
+ --role-team-strong: #25665d;
121
+ --role-admin: #765c9f;
122
+ --role-admin-strong: #59417e;
123
+ --role-manager: #a36f2f;
124
+ --role-manager-strong: #7b501f;
125
+
126
+ --badge-count-bg: var(--semantic-danger);
127
+ --badge-count-fg: var(--brand-white);
128
+ --on-fill-danger: var(--brand-white);
129
+ --on-fill-warning: #3a2a05;
130
+ --on-fill-success: #06281e;
131
+
132
+ --page-background:
133
+ radial-gradient(circle at 14% 8%, color-mix(in srgb, var(--brand-accent) 14%, transparent), transparent 26%),
134
+ linear-gradient(180deg, var(--brand-white) 0%, color-mix(in srgb, var(--brand-accent) 4%, var(--brand-white)) 54%, var(--brand-white) 100%);
135
+ --brand-panel-surface: linear-gradient(
136
+ 158deg,
137
+ color-mix(in srgb, var(--brand-surface-dark) 96%, var(--brand-accent)) 0%,
138
+ color-mix(in srgb, var(--brand-surface-dark) 86%, var(--brand-accent)) 55%,
139
+ color-mix(in srgb, var(--brand-surface-dark) 72%, var(--brand-accent)) 100%
140
+ );
141
+ --brand-panel-surface-raised: color-mix(in srgb, var(--brand-surface-dark) 76%, var(--brand-accent));
142
+ --brand-panel-foreground: var(--brand-white);
143
+ --brand-panel-muted: color-mix(in srgb, var(--brand-white) 68%, transparent);
144
+ --brand-panel-subtle: color-mix(in srgb, var(--brand-white) 48%, transparent);
145
+ --brand-panel-border: color-mix(in srgb, var(--brand-accent) 22%, transparent);
146
+ --row-sweep-tint: var(--foreground);
147
+ --surface-card: color-mix(in srgb, var(--foreground) 2%, var(--card) 98%);
148
+ --surface-card-light: var(--card);
149
+ --surface-card-padding: 1.25rem;
150
+ --stat-cell-padding: 1rem;
151
+ }
152
+
153
+ /* Dark mode redefines the primitives and semantic base before re-deriving L1. */
154
+ :root.dark,
155
+ :root[data-theme="dark"],
156
+ .theme-dark {
157
+ color-scheme: dark;
158
+ --brand-accent: #79a8df;
159
+ --brand-accent-soft: #9bbce2;
160
+ --brand-ink: #0b1220;
161
+ --brand-neutral-500: #9aa9bc;
162
+ --brand-neutral-300: #c7d2e1;
163
+ --brand-neutral-200: #dce4ee;
164
+ --brand-neutral-100: #111c2c;
165
+ --brand-white: #f8fafc;
166
+ --brand-border-subtle: rgba(148, 163, 184, 0.24);
167
+ --brand-surface-tint: rgba(121, 168, 223, 0.14);
168
+ --brand-surface-dark: rgba(8, 15, 27, 0.96);
169
+ --brand-shadow-soft: 0 20px 44px rgba(0, 0, 0, 0.44);
170
+ --brand-shadow-lift: 0 18px 36px rgba(0, 0, 0, 0.5);
171
+
172
+ --background: #0b1220;
173
+ --foreground: #edf2f8;
174
+ --card: #111c2c;
175
+ --card-foreground: #edf2f8;
176
+ --popover: #101a29;
177
+ --popover-foreground: #edf2f8;
178
+ --primary: #edf2f8;
179
+ --primary-foreground: #0b1220;
180
+ --secondary: #172438;
181
+ --secondary-foreground: #dce5f0;
182
+ --muted: rgba(148, 163, 184, 0.16);
183
+ --muted-foreground: #a6b4c6;
184
+ --foreground-inverse: #f8fafc;
185
+ --foreground-inverse-muted: rgba(248, 250, 252, 0.9);
186
+ --foreground-inverse-subtle: rgba(248, 250, 252, 0.84);
187
+ --accent: var(--brand-accent);
188
+ --accent-foreground: #0b1220;
189
+ --destructive: #d26969;
190
+ --destructive-foreground: #0b1220;
191
+ --border: rgba(148, 163, 184, 0.22);
192
+ --input: rgba(148, 163, 184, 0.17);
193
+ --ring: rgba(121, 168, 223, 0.4);
194
+
195
+ --semantic-info: #38bdf8;
196
+ --semantic-info-strong: #7dd3fc;
197
+ --semantic-special: #a78bfa;
198
+ --semantic-special-strong: #ddd6fe;
199
+ --semantic-warning: #fbbf24;
200
+ --semantic-warning-strong: #fde68a;
201
+ --semantic-success: #34d399;
202
+ --semantic-success-strong: #a7f3d0;
203
+ --semantic-danger: #fb7185;
204
+ --semantic-danger-strong: #fecdd3;
205
+ --semantic-danger-soft: #fda4af;
206
+ --semantic-neutral: #a1a1aa;
207
+ --semantic-neutral-strong: #d4d4d8;
208
+
209
+ --skeleton: color-mix(in srgb, var(--foreground) 9%, transparent);
210
+ --skeleton-strong: color-mix(in srgb, var(--foreground) 14%, transparent);
211
+ --skeleton-highlight: color-mix(in srgb, var(--brand-white) 12%, transparent);
212
+ --role-client: #79a8df;
213
+ --role-client-strong: #c5daf2;
214
+ --role-team: #5bc8b9;
215
+ --role-team-strong: #b8eee7;
216
+ --role-admin: #ad99d0;
217
+ --role-admin-strong: #ded5ed;
218
+ --role-manager: #e0aa61;
219
+ --role-manager-strong: #f4d6aa;
220
+ --badge-count-fg: #ffffff;
221
+ --on-fill-danger: #350a11;
222
+ --on-fill-warning: #3a2a05;
223
+ --on-fill-success: #06281e;
224
+
225
+ --page-background:
226
+ radial-gradient(circle at 14% 12%, color-mix(in srgb, var(--brand-accent) 17%, transparent), transparent 26%),
227
+ radial-gradient(circle at 82% 18%, color-mix(in srgb, var(--brand-accent) 10%, transparent), transparent 24%),
228
+ linear-gradient(180deg, var(--brand-surface-dark) 0%, var(--background) 100%);
229
+ --brand-panel-surface: linear-gradient(
230
+ 158deg,
231
+ color-mix(in srgb, var(--card) 84%, var(--brand-accent)) 0%,
232
+ color-mix(in srgb, var(--card) 72%, var(--brand-accent)) 52%,
233
+ color-mix(in srgb, var(--card) 60%, var(--brand-accent)) 100%
234
+ );
235
+ --brand-panel-surface-raised: color-mix(in srgb, var(--card) 72%, var(--brand-accent));
236
+ --surface-card: color-mix(in srgb, var(--foreground) 2%, var(--card) 98%);
237
+ --surface-card-light: color-mix(in srgb, var(--card) 92%, var(--brand-white) 8%);
238
+ }
239
+
240
+ /* Explicit light scope wins when a theme class/attribute is toggled at runtime. */
241
+ :root.light,
242
+ :root[data-theme="light"],
243
+ .theme-light {
244
+ color-scheme: light;
245
+ --background: var(--brand-white);
246
+ --foreground: var(--brand-ink);
247
+ --card: var(--brand-white);
248
+ --card-foreground: var(--brand-ink);
249
+ --popover: var(--brand-white);
250
+ --popover-foreground: var(--brand-ink);
251
+ --primary: var(--brand-ink);
252
+ --primary-foreground: var(--brand-white);
253
+ --secondary: var(--brand-neutral-100);
254
+ --secondary-foreground: var(--brand-ink);
255
+ --muted: rgba(203, 213, 225, 0.25);
256
+ --muted-foreground: var(--brand-neutral-500);
257
+ --foreground-inverse: var(--brand-white);
258
+ --foreground-inverse-muted: rgba(255, 255, 255, 0.88);
259
+ --foreground-inverse-subtle: rgba(255, 255, 255, 0.84);
260
+ --accent: var(--brand-accent);
261
+ --accent-foreground: var(--brand-white);
262
+ --destructive: #b43f3f;
263
+ --destructive-foreground: var(--brand-white);
264
+ --border: var(--brand-border-subtle);
265
+ --input: rgba(15, 23, 42, 0.09);
266
+ --ring: rgba(74, 125, 189, 0.42);
267
+ }
268
+
269
+ @media (max-width: 640px) {
270
+ :root {
271
+ --space-card-pad-x: 1.25rem;
272
+ --space-copy-bottom: 1.75rem;
273
+ }
274
+ }
@@ -0,0 +1,149 @@
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
+ @utility text-ui-micro {
10
+ font-family: var(--font-body), sans-serif;
11
+ font-size: var(--text-ui-micro);
12
+ font-weight: var(--font-weight-medium);
13
+ line-height: 1.3;
14
+ color: var(--muted-foreground);
15
+ }
16
+
17
+ @utility text-ui-label {
18
+ font-family: var(--font-body), sans-serif;
19
+ font-size: var(--text-ui-label);
20
+ font-weight: var(--font-weight-medium);
21
+ line-height: 1;
22
+ text-transform: uppercase;
23
+ letter-spacing: 0.14em;
24
+ color: var(--muted-foreground);
25
+ }
26
+
27
+ @utility text-ui-meta {
28
+ font-family: var(--font-body), sans-serif;
29
+ font-size: var(--text-ui-meta);
30
+ font-weight: var(--font-weight-regular);
31
+ line-height: 1.4;
32
+ color: var(--muted-foreground);
33
+ }
34
+
35
+ @utility text-ui-body {
36
+ font-family: var(--font-body), sans-serif;
37
+ font-size: var(--text-ui-body);
38
+ font-weight: var(--font-weight-regular);
39
+ line-height: 1.5;
40
+ color: var(--foreground);
41
+ }
42
+
43
+ @utility text-ui-card-title {
44
+ font-family: var(--font-body), sans-serif;
45
+ font-size: var(--text-ui-card-title);
46
+ font-weight: var(--font-weight-medium);
47
+ line-height: 1.3;
48
+ letter-spacing: -0.025em;
49
+ color: var(--foreground);
50
+ }
51
+
52
+ @utility text-ui-subhead {
53
+ font-family: var(--font-display), sans-serif;
54
+ font-size: var(--text-ui-subhead);
55
+ font-weight: var(--font-weight-bold);
56
+ line-height: 1.25;
57
+ letter-spacing: -0.02em;
58
+ color: var(--foreground);
59
+ }
60
+
61
+ @utility text-ui-panel-title {
62
+ font-family: var(--font-display), sans-serif;
63
+ font-size: var(--text-ui-panel-title);
64
+ font-weight: var(--font-weight-bold);
65
+ line-height: 1.2;
66
+ letter-spacing: -0.02em;
67
+ color: var(--foreground);
68
+ }
69
+
70
+ @utility text-ui-heading {
71
+ font-family: var(--font-display), sans-serif;
72
+ font-size: var(--text-ui-heading);
73
+ font-weight: var(--font-weight-bold);
74
+ line-height: 1.15;
75
+ letter-spacing: -0.02em;
76
+ color: var(--foreground);
77
+ }
78
+
79
+ @utility text-ui-title-sm {
80
+ font-family: var(--font-display), sans-serif;
81
+ font-size: var(--text-ui-title-sm);
82
+ font-weight: var(--font-weight-heavy);
83
+ line-height: 1.1;
84
+ letter-spacing: -0.03em;
85
+ color: var(--foreground);
86
+ }
87
+
88
+ @utility text-ui-title {
89
+ font-family: var(--font-display), sans-serif;
90
+ font-size: var(--text-ui-title);
91
+ font-weight: var(--font-weight-heavy);
92
+ line-height: 1.05;
93
+ letter-spacing: -0.03em;
94
+ color: var(--foreground);
95
+ }
96
+
97
+ @utility text-ui-metric {
98
+ font-family: var(--font-mono);
99
+ font-variant-numeric: tabular-nums;
100
+ font-size: var(--text-ui-metric);
101
+ font-weight: var(--font-weight-heavy);
102
+ line-height: 1;
103
+ letter-spacing: -0.04em;
104
+ color: var(--foreground);
105
+ }
106
+
107
+ @utility text-ui-metric-xl {
108
+ font-family: var(--font-display), sans-serif;
109
+ font-variant-numeric: tabular-nums;
110
+ font-size: var(--text-ui-metric-xl);
111
+ font-weight: var(--font-weight-heavy);
112
+ line-height: 0.95;
113
+ letter-spacing: -0.04em;
114
+ color: var(--foreground);
115
+ }
116
+
117
+ @utility text-ui-metric-display {
118
+ font-family: var(--font-display), sans-serif;
119
+ font-variant-numeric: tabular-nums;
120
+ font-size: var(--text-ui-metric-display);
121
+ font-weight: var(--font-weight-heavy);
122
+ line-height: 1;
123
+ letter-spacing: -0.04em;
124
+ color: var(--foreground);
125
+ }
126
+
127
+ /* Thin scrollbar for bounded surface lists. */
128
+ @utility scroll-thin {
129
+ overflow-y: auto;
130
+ overflow-y: overlay;
131
+ overflow-x: hidden;
132
+ scrollbar-width: thin;
133
+ scrollbar-color: color-mix(in srgb, var(--foreground) 18%, transparent) transparent;
134
+
135
+ &::-webkit-scrollbar {
136
+ width: 6px;
137
+ height: 6px;
138
+ }
139
+ &::-webkit-scrollbar-track {
140
+ background: transparent;
141
+ }
142
+ &::-webkit-scrollbar-thumb {
143
+ background-color: color-mix(in srgb, var(--foreground) 18%, transparent);
144
+ border-radius: 9999px;
145
+ }
146
+ &::-webkit-scrollbar-thumb:hover {
147
+ background-color: color-mix(in srgb, var(--foreground) 30%, transparent);
148
+ }
149
+ }
@@ -0,0 +1,139 @@
1
+ /* Legacy MQ primitive aliases for incremental consumer migration. */
2
+ :root {
3
+ --mq-ink-950: var(--brand-ink);
4
+ --mq-brand-500: var(--brand-accent);
5
+ --mq-brand-400: var(--brand-accent-soft);
6
+ --mq-neutral-500: var(--brand-neutral-500);
7
+ --mq-neutral-300: var(--brand-neutral-300);
8
+ --mq-neutral-200: var(--brand-neutral-200);
9
+ --mq-neutral-100: var(--brand-neutral-100);
10
+ --mq-white: var(--brand-white);
11
+ --mq-border-subtle: var(--brand-border-subtle);
12
+ --mq-surface-tint: var(--brand-surface-tint);
13
+ --mq-surface-dark: var(--brand-surface-dark);
14
+ --mq-shadow-soft: var(--brand-shadow-soft);
15
+ --mq-shadow-lift: var(--brand-shadow-lift);
16
+ }
17
+
18
+ @utility portal-micro {
19
+ font-family: var(--font-body), sans-serif;
20
+ font-size: var(--text-ui-micro);
21
+ font-weight: var(--font-weight-medium);
22
+ line-height: 1.3;
23
+ color: var(--muted-foreground);
24
+ }
25
+ @utility portal-label {
26
+ font-family: var(--font-body), sans-serif;
27
+ font-size: var(--text-ui-label);
28
+ font-weight: var(--font-weight-medium);
29
+ line-height: 1;
30
+ text-transform: uppercase;
31
+ letter-spacing: 0.14em;
32
+ color: var(--muted-foreground);
33
+ }
34
+ @utility portal-meta {
35
+ font-family: var(--font-body), sans-serif;
36
+ font-size: var(--text-ui-meta);
37
+ font-weight: var(--font-weight-regular);
38
+ line-height: 1.4;
39
+ color: var(--muted-foreground);
40
+ }
41
+ @utility portal-body {
42
+ font-family: var(--font-body), sans-serif;
43
+ font-size: var(--text-ui-body);
44
+ font-weight: var(--font-weight-regular);
45
+ line-height: 1.5;
46
+ color: var(--foreground);
47
+ }
48
+ @utility portal-card-title {
49
+ font-family: var(--font-body), sans-serif;
50
+ font-size: var(--text-ui-card-title);
51
+ font-weight: var(--font-weight-medium);
52
+ line-height: 1.3;
53
+ letter-spacing: -0.025em;
54
+ color: var(--foreground);
55
+ }
56
+ @utility portal-subhead {
57
+ font-family: var(--font-display), sans-serif;
58
+ font-size: var(--text-ui-subhead);
59
+ font-weight: var(--font-weight-bold);
60
+ line-height: 1.25;
61
+ letter-spacing: -0.02em;
62
+ color: var(--foreground);
63
+ }
64
+ @utility portal-panel-title {
65
+ font-family: var(--font-display), sans-serif;
66
+ font-size: var(--text-ui-panel-title);
67
+ font-weight: var(--font-weight-bold);
68
+ line-height: 1.2;
69
+ letter-spacing: -0.02em;
70
+ color: var(--foreground);
71
+ }
72
+ @utility portal-heading {
73
+ font-family: var(--font-display), sans-serif;
74
+ font-size: var(--text-ui-heading);
75
+ font-weight: var(--font-weight-bold);
76
+ line-height: 1.15;
77
+ letter-spacing: -0.02em;
78
+ color: var(--foreground);
79
+ }
80
+ @utility portal-title-sm {
81
+ font-family: var(--font-display), sans-serif;
82
+ font-size: var(--text-ui-title-sm);
83
+ font-weight: var(--font-weight-heavy);
84
+ line-height: 1.1;
85
+ letter-spacing: -0.03em;
86
+ color: var(--foreground);
87
+ }
88
+ @utility portal-title {
89
+ font-family: var(--font-display), sans-serif;
90
+ font-size: var(--text-ui-title);
91
+ font-weight: var(--font-weight-heavy);
92
+ line-height: 1.05;
93
+ letter-spacing: -0.03em;
94
+ color: var(--foreground);
95
+ }
96
+ @utility portal-metric {
97
+ font-family: var(--font-mono);
98
+ font-variant-numeric: tabular-nums;
99
+ font-size: var(--text-ui-metric);
100
+ font-weight: var(--font-weight-heavy);
101
+ line-height: 1;
102
+ letter-spacing: -0.04em;
103
+ color: var(--foreground);
104
+ }
105
+ @utility portal-metric-xl {
106
+ font-family: var(--font-display), sans-serif;
107
+ font-variant-numeric: tabular-nums;
108
+ font-size: var(--text-ui-metric-xl);
109
+ font-weight: var(--font-weight-heavy);
110
+ line-height: 0.95;
111
+ letter-spacing: -0.04em;
112
+ color: var(--foreground);
113
+ }
114
+ @utility portal-metric-display {
115
+ font-family: var(--font-display), sans-serif;
116
+ font-variant-numeric: tabular-nums;
117
+ font-size: var(--text-ui-metric-display);
118
+ font-weight: var(--font-weight-heavy);
119
+ line-height: 1;
120
+ letter-spacing: -0.04em;
121
+ color: var(--foreground);
122
+ }
123
+ @utility portal-scroll {
124
+ overflow-y: auto;
125
+ overflow-y: overlay;
126
+ overflow-x: hidden;
127
+ scrollbar-width: thin;
128
+ scrollbar-color: color-mix(in srgb, var(--foreground) 18%, transparent) transparent;
129
+
130
+ &::-webkit-scrollbar { width: 6px; height: 6px; }
131
+ &::-webkit-scrollbar-track { background: transparent; }
132
+ &::-webkit-scrollbar-thumb {
133
+ background-color: color-mix(in srgb, var(--foreground) 18%, transparent);
134
+ border-radius: 9999px;
135
+ }
136
+ &::-webkit-scrollbar-thumb:hover {
137
+ background-color: color-mix(in srgb, var(--foreground) 30%, transparent);
138
+ }
139
+ }
package/themes/mq.css ADDED
@@ -0,0 +1,177 @@
1
+ /* MQ compatibility palette. Import after @brightweblabs/theme/css. */
2
+ :root {
3
+ --brand-accent: #5bc5f2;
4
+ --brand-accent-soft: #6fc4e7;
5
+ --brand-ink: #0a151a;
6
+ --brand-neutral-500: #8e8f9a;
7
+ --brand-neutral-300: #bfc0cf;
8
+ --brand-neutral-200: #e9e9e9;
9
+ --brand-neutral-100: #f4f8fb;
10
+ --brand-white: #ffffff;
11
+ --brand-border-subtle: rgba(10, 21, 26, 0.09);
12
+ --brand-surface-tint: rgba(91, 197, 242, 0.08);
13
+ --brand-surface-dark: rgba(10, 21, 26, 0.94);
14
+ --brand-shadow-soft: 0 20px 44px rgba(10, 21, 26, 0.1);
15
+ --brand-shadow-lift: 0 15px 20px rgba(84, 84, 84, 0.5);
16
+
17
+ --background: var(--brand-white);
18
+ --foreground: var(--brand-ink);
19
+ --card: var(--brand-white);
20
+ --card-foreground: var(--brand-ink);
21
+ --popover: var(--brand-white);
22
+ --popover-foreground: var(--brand-ink);
23
+ --primary: var(--brand-ink);
24
+ --primary-foreground: var(--brand-white);
25
+ --secondary: var(--brand-neutral-100);
26
+ --secondary-foreground: var(--brand-ink);
27
+ --muted: rgba(191, 192, 207, 0.18);
28
+ --muted-foreground: var(--brand-neutral-500);
29
+ --foreground-inverse: var(--brand-white);
30
+ --foreground-inverse-muted: rgba(255, 255, 255, 0.88);
31
+ --foreground-inverse-subtle: rgba(255, 255, 255, 0.84);
32
+ --accent: var(--brand-accent);
33
+ --accent-foreground: var(--brand-ink);
34
+ --destructive: #b43f3f;
35
+ --destructive-foreground: var(--brand-white);
36
+ --border: var(--brand-border-subtle);
37
+ --input: rgba(10, 21, 26, 0.08);
38
+ --ring: rgba(91, 197, 242, 0.42);
39
+
40
+ --role-client: #3b82f6;
41
+ --role-client-strong: #1e40af;
42
+ --role-team: #0d9488;
43
+ --role-team-strong: #0f766e;
44
+ --role-admin: #7c3aed;
45
+ --role-admin-strong: #6d28d9;
46
+ --role-manager: #d97706;
47
+ --role-manager-strong: #b45309;
48
+ --badge-count-fg: #ffffff;
49
+ --on-fill-danger: #ffffff;
50
+ --on-fill-warning: #3a2a05;
51
+ --on-fill-success: #06281e;
52
+
53
+ --page-background:
54
+ radial-gradient(circle at top left, rgba(91, 197, 242, 0.12), transparent 24%),
55
+ linear-gradient(180deg, #ffffff 0%, #f7fbff 54%, #ffffff 100%);
56
+ --brand-panel-surface: linear-gradient(158deg, #02070d 0%, #06111c 30%, #071d2b 63%, #123747 100%);
57
+ --brand-panel-surface-raised: #0b2634;
58
+ --brand-panel-foreground: #f6fbff;
59
+ --brand-panel-muted: rgba(246, 251, 255, 0.66);
60
+ --brand-panel-subtle: rgba(246, 251, 255, 0.46);
61
+ --brand-panel-border: rgba(145, 211, 241, 0.2);
62
+ }
63
+
64
+ :root.dark,
65
+ :root[data-theme="dark"],
66
+ .theme-dark {
67
+ --brand-accent: #5bc5f2;
68
+ --brand-accent-soft: #6fc4e7;
69
+ --brand-ink: #061118;
70
+ --brand-neutral-500: #9ca5b5;
71
+ --brand-neutral-300: #c9d5e6;
72
+ --brand-neutral-200: #dee6f2;
73
+ --brand-neutral-100: #0f1b25;
74
+ --brand-white: #ffffff;
75
+ --brand-border-subtle: rgba(153, 184, 206, 0.26);
76
+ --brand-surface-tint: rgba(91, 197, 242, 0.08);
77
+ --brand-surface-dark: rgba(10, 21, 26, 0.94);
78
+ --brand-shadow-soft: 0 20px 44px rgba(0, 0, 0, 0.45);
79
+ --brand-shadow-lift: 0 16px 44px rgba(0, 0, 0, 0.5);
80
+
81
+ --background: #08131b;
82
+ --foreground: #edf6ff;
83
+ --card: #0d1d29;
84
+ --card-foreground: #edf6ff;
85
+ --popover: #0c1a25;
86
+ --popover-foreground: #edf6ff;
87
+ --primary: #edf6ff;
88
+ --primary-foreground: #08131b;
89
+ --secondary: #112433;
90
+ --secondary-foreground: #dceaf7;
91
+ --muted: rgba(132, 170, 198, 0.16);
92
+ --muted-foreground: #9eb6cd;
93
+ --foreground-inverse: #f7fbff;
94
+ --foreground-inverse-muted: rgba(247, 251, 255, 0.9);
95
+ --foreground-inverse-subtle: rgba(247, 251, 255, 0.84);
96
+ --accent: #7bd8ff;
97
+ --accent-foreground: #061118;
98
+ --destructive: #d26969;
99
+ --destructive-foreground: #08131c;
100
+ --border: rgba(132, 170, 198, 0.22);
101
+ --input: rgba(132, 170, 198, 0.16);
102
+ --ring: rgba(123, 216, 255, 0.38);
103
+
104
+ --semantic-info: #38bdf8;
105
+ --semantic-info-strong: #7dd3fc;
106
+ --semantic-special: #a78bfa;
107
+ --semantic-special-strong: #ddd6fe;
108
+ --semantic-warning: #fbbf24;
109
+ --semantic-warning-strong: #fde68a;
110
+ --semantic-success: #34d399;
111
+ --semantic-success-strong: #a7f3d0;
112
+ --semantic-danger: #fb7185;
113
+ --semantic-danger-strong: #fecdd3;
114
+ --semantic-danger-soft: #fda4af;
115
+ --semantic-neutral: #a1a1aa;
116
+ --semantic-neutral-strong: #d4d4d8;
117
+ --role-client: #60a5fa;
118
+ --role-client-strong: #bfdbfe;
119
+ --role-team: #2dd4bf;
120
+ --role-team-strong: #99f6e4;
121
+ --role-admin: #a78bfa;
122
+ --role-admin-strong: #ddd6fe;
123
+ --role-manager: #fbbf24;
124
+ --role-manager-strong: #fde68a;
125
+ --badge-count-fg: #ffffff;
126
+ --on-fill-danger: #350a11;
127
+ --on-fill-warning: #3a2a05;
128
+ --on-fill-success: #06281e;
129
+
130
+ --page-background:
131
+ radial-gradient(circle at 14% 12%, rgba(123, 216, 255, 0.17), transparent 26%),
132
+ radial-gradient(circle at 82% 18%, rgba(54, 123, 164, 0.18), transparent 24%),
133
+ linear-gradient(180deg, #071119 0%, #0b1621 48%, #08121c 100%);
134
+ --brand-panel-surface: linear-gradient(158deg, #0c2433 0%, #143b4e 52%, #1b4f66 100%);
135
+ --brand-panel-surface-raised: #0b2634;
136
+ --brand-panel-foreground: #f6fbff;
137
+ --brand-panel-muted: rgba(246, 251, 255, 0.66);
138
+ --brand-panel-subtle: rgba(246, 251, 255, 0.46);
139
+ --brand-panel-border: color-mix(in srgb, var(--accent) 20%, transparent);
140
+ }
141
+
142
+ :root.light,
143
+ :root[data-theme="light"],
144
+ .theme-light {
145
+ --brand-accent: #5bc5f2;
146
+ --brand-accent-soft: #6fc4e7;
147
+ --brand-ink: #0a151a;
148
+ --brand-neutral-500: #8e8f9a;
149
+ --brand-neutral-300: #bfc0cf;
150
+ --brand-neutral-200: #e9e9e9;
151
+ --brand-neutral-100: #f4f8fb;
152
+ --brand-white: #ffffff;
153
+ --brand-border-subtle: rgba(10, 21, 26, 0.09);
154
+ --brand-surface-tint: rgba(91, 197, 242, 0.08);
155
+ --brand-surface-dark: rgba(10, 21, 26, 0.94);
156
+ --brand-shadow-soft: 0 20px 44px rgba(10, 21, 26, 0.1);
157
+ --brand-shadow-lift: 0 15px 20px rgba(84, 84, 84, 0.5);
158
+ --background: var(--brand-white);
159
+ --foreground: var(--brand-ink);
160
+ --card: var(--brand-white);
161
+ --card-foreground: var(--brand-ink);
162
+ --popover: var(--brand-white);
163
+ --popover-foreground: var(--brand-ink);
164
+ --primary: var(--brand-ink);
165
+ --primary-foreground: var(--brand-white);
166
+ --secondary: var(--brand-neutral-100);
167
+ --secondary-foreground: var(--brand-ink);
168
+ --muted: rgba(191, 192, 207, 0.18);
169
+ --muted-foreground: var(--brand-neutral-500);
170
+ --accent: var(--brand-accent);
171
+ --accent-foreground: var(--brand-ink);
172
+ --destructive: #b43f3f;
173
+ --destructive-foreground: var(--brand-white);
174
+ --border: var(--brand-border-subtle);
175
+ --input: rgba(10, 21, 26, 0.08);
176
+ --ring: rgba(91, 197, 242, 0.42);
177
+ }