@tonycodes-ui/mortar 0.0.0-stage → 0.12.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/AGENTS.md +10 -0
- package/CHANGELOG.md +268 -0
- package/CONTRIBUTING.md +60 -0
- package/DESIGN.md +51 -0
- package/LICENSE +21 -0
- package/README.md +155 -2
- package/TESTING.md +83 -0
- package/baseline-policy.json +16 -0
- package/bin/mortar.mjs +258 -0
- package/catalog.json +9900 -0
- package/cli/audit.mjs +943 -0
- package/cli/data.mjs +176 -0
- package/cli/mcp.mjs +216 -0
- package/cli/migrations.mjs +128 -0
- package/cli/packet.mjs +267 -0
- package/cli/search.mjs +246 -0
- package/cli/tools.mjs +229 -0
- package/design-principles.json +30 -0
- package/dist/agent-data.json +1 -0
- package/dist/application.d.ts +340 -0
- package/dist/application.js +240 -0
- package/dist/auth.d.ts +121 -0
- package/dist/auth.js +97 -0
- package/dist/brand.d.ts +69 -0
- package/dist/brand.js +266 -0
- package/dist/calendar.d.ts +75 -0
- package/dist/calendar.js +310 -0
- package/dist/choice.d.ts +36 -0
- package/dist/choice.js +36 -0
- package/dist/composer.d.ts +28 -0
- package/dist/composer.js +47 -0
- package/dist/display.d.ts +136 -0
- package/dist/display.js +75 -0
- package/dist/docs.d.ts +145 -0
- package/dist/docs.js +141 -0
- package/dist/ecommerce.d.ts +261 -0
- package/dist/ecommerce.js +177 -0
- package/dist/feedback.d.ts +80 -0
- package/dist/feedback.js +98 -0
- package/dist/foundation.d.ts +42 -0
- package/dist/foundation.js +121 -0
- package/dist/heading.d.ts +5 -0
- package/dist/heading.js +9 -0
- package/dist/icons.d.ts +50 -0
- package/dist/icons.js +70 -0
- package/dist/illustration.d.ts +47 -0
- package/dist/illustration.js +47 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +18 -0
- package/dist/inspection.d.ts +24 -0
- package/dist/inspection.js +14 -0
- package/dist/internal.d.ts +514 -0
- package/dist/internal.js +332 -0
- package/dist/layout.d.ts +107 -0
- package/dist/layout.js +66 -0
- package/dist/marketing-sections.d.ts +161 -0
- package/dist/marketing-sections.js +58 -0
- package/dist/marketing.d.ts +277 -0
- package/dist/marketing.js +163 -0
- package/dist/navigation.d.ts +35 -0
- package/dist/navigation.js +44 -0
- package/dist/primitives.d.ts +258 -0
- package/dist/primitives.js +244 -0
- package/dist/showcase.d.ts +29 -0
- package/dist/showcase.js +10 -0
- package/dist/workspace.d.ts +80 -0
- package/dist/workspace.js +48 -0
- package/docs/agents.md +127 -0
- package/docs/auth-flows.md +71 -0
- package/docs/migrating-to-0.6.md +94 -0
- package/docs/theming.md +170 -0
- package/package.json +94 -4
- package/skills/mortar/SKILL.md +36 -0
- package/src/application.css +1487 -0
- package/src/application.tsx +1413 -0
- package/src/auth.tsx +452 -0
- package/src/brand.ts +335 -0
- package/src/calendar.css +468 -0
- package/src/calendar.tsx +868 -0
- package/src/choice.tsx +240 -0
- package/src/composer.tsx +158 -0
- package/src/data.css +690 -0
- package/src/display.tsx +452 -0
- package/src/docs.css +704 -0
- package/src/docs.tsx +737 -0
- package/src/ecommerce.css +810 -0
- package/src/ecommerce.tsx +1033 -0
- package/src/feedback.tsx +388 -0
- package/src/foundation.css +1867 -0
- package/src/foundation.tsx +227 -0
- package/src/heading.ts +13 -0
- package/src/icons.tsx +237 -0
- package/src/illustration.tsx +169 -0
- package/src/index.ts +233 -0
- package/src/inspection.tsx +91 -0
- package/src/internal.tsx +700 -0
- package/src/layout.tsx +342 -0
- package/src/marketing-sections.tsx +621 -0
- package/src/marketing.css +2579 -0
- package/src/marketing.tsx +1235 -0
- package/src/navigation.tsx +118 -0
- package/src/overlays.css +350 -0
- package/src/primitives.tsx +1135 -0
- package/src/showcase.tsx +120 -0
- package/src/tokens.css +449 -0
- package/src/workspace.tsx +333 -0
- package/styles.css +56 -0
package/src/showcase.tsx
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { componentRoot, cx } from "./internal.js";
|
|
3
|
+
|
|
4
|
+
/** Framed product screenshot or illustration for heroes and feature sections. */
|
|
5
|
+
export function MockWindow({
|
|
6
|
+
id,
|
|
7
|
+
className,
|
|
8
|
+
label,
|
|
9
|
+
address,
|
|
10
|
+
variant = "browser",
|
|
11
|
+
children,
|
|
12
|
+
}: {
|
|
13
|
+
id?: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
/** Accessible description of what the mock shows. */
|
|
16
|
+
label: string;
|
|
17
|
+
/** Optional URL or file name shown in the title bar. */
|
|
18
|
+
address?: string;
|
|
19
|
+
/** browser: title bar with dots. app: title bar without dots. plain: no chrome. phone: a portrait handset frame. */
|
|
20
|
+
variant?: "browser" | "app" | "plain" | "phone";
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}) {
|
|
23
|
+
return (
|
|
24
|
+
<figure
|
|
25
|
+
id={id}
|
|
26
|
+
className={cx("m-mock-window", className)}
|
|
27
|
+
data-variant={variant === "browser" ? undefined : variant}
|
|
28
|
+
aria-label={label}
|
|
29
|
+
{...componentRoot("MockWindow")}
|
|
30
|
+
>
|
|
31
|
+
{variant !== "plain" && variant !== "phone" && (
|
|
32
|
+
<div className="m-mock-bar" aria-hidden="true">
|
|
33
|
+
<span className="m-mock-dots">
|
|
34
|
+
<i />
|
|
35
|
+
<i />
|
|
36
|
+
<i />
|
|
37
|
+
</span>
|
|
38
|
+
{address && <span className="m-mock-address">{address}</span>}
|
|
39
|
+
</div>
|
|
40
|
+
)}
|
|
41
|
+
<div className="m-mock-body">{children}</div>
|
|
42
|
+
</figure>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ChatMessage {
|
|
47
|
+
from: "user" | "assistant";
|
|
48
|
+
content: ReactNode;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Static, illustrative chat conversation for marketing a conversational product. */
|
|
52
|
+
export function ChatPreview({
|
|
53
|
+
id,
|
|
54
|
+
className,
|
|
55
|
+
title,
|
|
56
|
+
status,
|
|
57
|
+
messages,
|
|
58
|
+
typing = false,
|
|
59
|
+
suggestions = [],
|
|
60
|
+
placeholder = "Type a message…",
|
|
61
|
+
assistantName = "Assistant",
|
|
62
|
+
}: {
|
|
63
|
+
id?: string;
|
|
64
|
+
className?: string;
|
|
65
|
+
title: string;
|
|
66
|
+
status?: string;
|
|
67
|
+
messages: ChatMessage[];
|
|
68
|
+
typing?: boolean;
|
|
69
|
+
suggestions?: string[];
|
|
70
|
+
placeholder?: string;
|
|
71
|
+
assistantName?: string;
|
|
72
|
+
}) {
|
|
73
|
+
return (
|
|
74
|
+
<figure
|
|
75
|
+
id={id}
|
|
76
|
+
className={cx("m-chat-preview", className)}
|
|
77
|
+
aria-label={`${title} conversation`}
|
|
78
|
+
{...componentRoot("ChatPreview")}
|
|
79
|
+
>
|
|
80
|
+
<header>
|
|
81
|
+
<span className="m-chat-avatar" aria-hidden="true" />
|
|
82
|
+
<span>
|
|
83
|
+
<strong>{title}</strong>
|
|
84
|
+
{status && <small>{status}</small>}
|
|
85
|
+
</span>
|
|
86
|
+
</header>
|
|
87
|
+
<ol className="m-chat-log">
|
|
88
|
+
{messages.map((message, i) => (
|
|
89
|
+
<li key={i} data-from={message.from}>
|
|
90
|
+
<span className="m-sr-only">
|
|
91
|
+
{message.from === "user" ? "Visitor" : assistantName}:
|
|
92
|
+
</span>
|
|
93
|
+
<div className="m-chat-bubble">{message.content}</div>
|
|
94
|
+
</li>
|
|
95
|
+
))}
|
|
96
|
+
{typing && (
|
|
97
|
+
<li data-from="assistant">
|
|
98
|
+
<span className="m-chat-typing">
|
|
99
|
+
<span className="m-sr-only">{assistantName} is typing</span>
|
|
100
|
+
<i aria-hidden="true" />
|
|
101
|
+
<i aria-hidden="true" />
|
|
102
|
+
<i aria-hidden="true" />
|
|
103
|
+
</span>
|
|
104
|
+
</li>
|
|
105
|
+
)}
|
|
106
|
+
</ol>
|
|
107
|
+
{suggestions.length > 0 && (
|
|
108
|
+
<ul className="m-chat-suggestions" aria-label="Suggested replies">
|
|
109
|
+
{suggestions.map((s) => (
|
|
110
|
+
<li key={s}>{s}</li>
|
|
111
|
+
))}
|
|
112
|
+
</ul>
|
|
113
|
+
)}
|
|
114
|
+
<div className="m-chat-composer" aria-hidden="true">
|
|
115
|
+
<span>{placeholder}</span>
|
|
116
|
+
<span className="m-chat-send" />
|
|
117
|
+
</div>
|
|
118
|
+
</figure>
|
|
119
|
+
);
|
|
120
|
+
}
|
package/src/tokens.css
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/* Mortar tokens, in three layers.
|
|
2
|
+
1. Brand contract: a brand declares --m-brand-l-* (light), --m-brand-d-*
|
|
3
|
+
(dark) and --m-brand-font / --m-brand-font-heading, and nothing else.
|
|
4
|
+
Every value is optional; omitted surfaces keep the defaults below.
|
|
5
|
+
2. Appearance: resolves the contract into the live --m-* tokens and into the
|
|
6
|
+
--m-inv-* tokens (the opposite appearance, used by inverse bands), so
|
|
7
|
+
dark mode and inverse sections never need brand-specific CSS. Hover and
|
|
8
|
+
active mix towards ink, which keeps on-primary contrast at least as high
|
|
9
|
+
as on the primary itself; selected tints the paper. --m-accent-fill is
|
|
10
|
+
an image (the brand's accent gradient, or flat accent) for opt-in
|
|
11
|
+
accent buttons and bands, painted over background-color: --m-accent.
|
|
12
|
+
3. Scales: type, space, radius, sizing, density and stacking.
|
|
13
|
+
Status colours deliberately differ from brand colours. A light container
|
|
14
|
+
inside a dark document resolves light. */
|
|
15
|
+
|
|
16
|
+
/* 1. Brand contract */
|
|
17
|
+
|
|
18
|
+
/* Every brand starts from an empty contract, so a brand never inherits values
|
|
19
|
+
from an outer one. Zero specificity: any brand rule wins, in any order. */
|
|
20
|
+
:where([data-mortar-brand]) {
|
|
21
|
+
--m-brand-l-primary: initial;
|
|
22
|
+
--m-brand-l-primary-hover: initial;
|
|
23
|
+
--m-brand-l-primary-active: initial;
|
|
24
|
+
--m-brand-l-on-primary: initial;
|
|
25
|
+
--m-brand-l-accent: initial;
|
|
26
|
+
--m-brand-l-on-accent: initial;
|
|
27
|
+
--m-brand-l-focus: initial;
|
|
28
|
+
--m-brand-l-link: initial;
|
|
29
|
+
--m-brand-l-selected: initial;
|
|
30
|
+
--m-brand-l-paper: initial;
|
|
31
|
+
--m-brand-l-surface: initial;
|
|
32
|
+
--m-brand-l-sunken: initial;
|
|
33
|
+
--m-brand-l-accent-gradient: initial;
|
|
34
|
+
--m-brand-d-primary: initial;
|
|
35
|
+
--m-brand-d-primary-hover: initial;
|
|
36
|
+
--m-brand-d-primary-active: initial;
|
|
37
|
+
--m-brand-d-on-primary: initial;
|
|
38
|
+
--m-brand-d-accent: initial;
|
|
39
|
+
--m-brand-d-on-accent: initial;
|
|
40
|
+
--m-brand-d-focus: initial;
|
|
41
|
+
--m-brand-d-link: initial;
|
|
42
|
+
--m-brand-d-selected: initial;
|
|
43
|
+
--m-brand-d-paper: initial;
|
|
44
|
+
--m-brand-d-surface: initial;
|
|
45
|
+
--m-brand-d-sunken: initial;
|
|
46
|
+
--m-brand-d-accent-gradient: initial;
|
|
47
|
+
--m-brand-font: initial;
|
|
48
|
+
--m-brand-font-heading: initial;
|
|
49
|
+
}
|
|
50
|
+
/* Neutral: the appearance fallbacks supply its colours; it keeps its tuned
|
|
51
|
+
interaction states. */
|
|
52
|
+
:root:not([data-mortar-brand]),
|
|
53
|
+
[data-mortar-brand="neutral"] {
|
|
54
|
+
--m-brand-l-primary-hover: #29292c;
|
|
55
|
+
--m-brand-l-primary-active: #3a3a3c;
|
|
56
|
+
--m-brand-l-selected: #f2f2f4;
|
|
57
|
+
--m-brand-d-primary-hover: #e5e5ea;
|
|
58
|
+
--m-brand-d-primary-active: #c7c7cc;
|
|
59
|
+
--m-brand-d-selected: #1c1c1e;
|
|
60
|
+
}
|
|
61
|
+
[data-mortar-brand="green"] {
|
|
62
|
+
--m-brand-l-primary: #047857;
|
|
63
|
+
--m-brand-l-primary-hover: #065f46;
|
|
64
|
+
--m-brand-l-primary-active: #064e3b;
|
|
65
|
+
--m-brand-l-on-primary: #ffffff;
|
|
66
|
+
--m-brand-l-selected: #e6f5ed;
|
|
67
|
+
--m-brand-d-primary: #6ee7b7;
|
|
68
|
+
--m-brand-d-primary-hover: #a7f3d0;
|
|
69
|
+
--m-brand-d-primary-active: #34d399;
|
|
70
|
+
--m-brand-d-on-primary: #022c22;
|
|
71
|
+
--m-brand-d-focus: #6ee7b7;
|
|
72
|
+
--m-brand-d-link: #6ee7b7;
|
|
73
|
+
--m-brand-d-selected: #062d23;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* 2. Appearance. A branded element without its own appearance resolves in
|
|
77
|
+
light, or in dark inside a dark-appearance ancestor. */
|
|
78
|
+
:root,
|
|
79
|
+
[data-mortar-appearance="light"],
|
|
80
|
+
[data-mortar-brand]:not([data-mortar-appearance]) {
|
|
81
|
+
--m-paper: var(--m-brand-l-paper, #ffffff);
|
|
82
|
+
--m-surface: var(--m-brand-l-surface, #ffffff);
|
|
83
|
+
--m-sunken: var(--m-brand-l-sunken, #f5f5f7);
|
|
84
|
+
--m-line: #e5e5ea;
|
|
85
|
+
--m-line-strong: #8b8b90;
|
|
86
|
+
--m-ink: #000000;
|
|
87
|
+
--m-secondary: #3a3a3c;
|
|
88
|
+
--m-muted: #6e6e73;
|
|
89
|
+
--m-success: #1f7a36;
|
|
90
|
+
--m-warning: #945700;
|
|
91
|
+
--m-danger: #c70014;
|
|
92
|
+
--m-info: #0060c7;
|
|
93
|
+
--m-on-feedback: #ffffff;
|
|
94
|
+
--m-code-bg: #000000;
|
|
95
|
+
--m-code-line: rgb(255 255 255 / 0.12);
|
|
96
|
+
--m-code-ink: #f5f5f7;
|
|
97
|
+
--m-code-dim: #8b8b90;
|
|
98
|
+
--m-float: 0 12px 32px -12px rgb(0 0 0 / 0.14);
|
|
99
|
+
--m-scrim: rgb(0 0 0 / 0.5);
|
|
100
|
+
--m-swatch-ring: rgb(0 0 0 / 0.12);
|
|
101
|
+
--m-primary: var(--m-brand-l-primary, #000000);
|
|
102
|
+
--m-primary-hover: var(
|
|
103
|
+
--m-brand-l-primary-hover,
|
|
104
|
+
color-mix(in oklab, var(--m-primary) 85%, var(--m-ink))
|
|
105
|
+
);
|
|
106
|
+
--m-primary-active: var(
|
|
107
|
+
--m-brand-l-primary-active,
|
|
108
|
+
color-mix(in oklab, var(--m-primary) 72%, var(--m-ink))
|
|
109
|
+
);
|
|
110
|
+
--m-on-primary: var(--m-brand-l-on-primary, #ffffff);
|
|
111
|
+
--m-accent: var(--m-brand-l-accent, var(--m-primary));
|
|
112
|
+
--m-on-accent: var(--m-brand-l-on-accent, var(--m-on-primary));
|
|
113
|
+
--m-accent-fill: var(
|
|
114
|
+
--m-brand-l-accent-gradient,
|
|
115
|
+
linear-gradient(var(--m-accent), var(--m-accent))
|
|
116
|
+
);
|
|
117
|
+
--m-focus: var(--m-brand-l-focus, var(--m-primary));
|
|
118
|
+
--m-link: var(--m-brand-l-link, var(--m-primary));
|
|
119
|
+
--m-selected: var(
|
|
120
|
+
--m-brand-l-selected,
|
|
121
|
+
color-mix(in oklab, var(--m-primary) 8%, var(--m-paper))
|
|
122
|
+
);
|
|
123
|
+
--m-inv-color-scheme: dark;
|
|
124
|
+
--m-inv-paper: var(--m-brand-d-paper, #000000);
|
|
125
|
+
--m-inv-surface: var(--m-brand-d-surface, #1c1c1e);
|
|
126
|
+
--m-inv-sunken: var(--m-brand-d-sunken, #1c1c1e);
|
|
127
|
+
--m-inv-line: #3a3a3c;
|
|
128
|
+
--m-inv-line-strong: #727278;
|
|
129
|
+
--m-inv-ink: #f5f5f7;
|
|
130
|
+
--m-inv-secondary: #c7c7cc;
|
|
131
|
+
--m-inv-muted: #a1a1a6;
|
|
132
|
+
--m-inv-success: #30d158;
|
|
133
|
+
--m-inv-warning: #ffd60a;
|
|
134
|
+
--m-inv-danger: #ff6961;
|
|
135
|
+
--m-inv-info: #5aa9ff;
|
|
136
|
+
--m-inv-on-feedback: #000000;
|
|
137
|
+
--m-inv-primary: var(--m-brand-d-primary, #ffffff);
|
|
138
|
+
--m-inv-primary-hover: var(
|
|
139
|
+
--m-brand-d-primary-hover,
|
|
140
|
+
color-mix(in oklab, var(--m-inv-primary) 85%, var(--m-inv-ink))
|
|
141
|
+
);
|
|
142
|
+
--m-inv-primary-active: var(
|
|
143
|
+
--m-brand-d-primary-active,
|
|
144
|
+
color-mix(in oklab, var(--m-inv-primary) 72%, var(--m-inv-ink))
|
|
145
|
+
);
|
|
146
|
+
--m-inv-on-primary: var(--m-brand-d-on-primary, #000000);
|
|
147
|
+
--m-inv-accent: var(--m-brand-d-accent, var(--m-inv-primary));
|
|
148
|
+
--m-inv-on-accent: var(--m-brand-d-on-accent, var(--m-inv-on-primary));
|
|
149
|
+
--m-inv-accent-fill: var(
|
|
150
|
+
--m-brand-d-accent-gradient,
|
|
151
|
+
linear-gradient(var(--m-inv-accent), var(--m-inv-accent))
|
|
152
|
+
);
|
|
153
|
+
--m-inv-focus: var(--m-brand-d-focus, var(--m-inv-primary));
|
|
154
|
+
--m-inv-link: var(--m-brand-d-link, var(--m-inv-ink));
|
|
155
|
+
--m-inv-selected: var(
|
|
156
|
+
--m-brand-d-selected,
|
|
157
|
+
color-mix(in oklab, var(--m-inv-primary) 10%, var(--m-inv-paper))
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
[data-mortar] {
|
|
161
|
+
color-scheme: light;
|
|
162
|
+
}
|
|
163
|
+
[data-mortar-appearance="dark"],
|
|
164
|
+
[data-mortar-appearance="dark"]
|
|
165
|
+
[data-mortar-brand]:not([data-mortar-appearance]) {
|
|
166
|
+
color-scheme: dark;
|
|
167
|
+
--m-paper: var(--m-brand-d-paper, #000000);
|
|
168
|
+
--m-surface: var(--m-brand-d-surface, #0e0e10);
|
|
169
|
+
--m-sunken: var(--m-brand-d-sunken, #1c1c1e);
|
|
170
|
+
--m-line: #29292c;
|
|
171
|
+
--m-line-strong: #727278;
|
|
172
|
+
--m-ink: #f5f5f7;
|
|
173
|
+
--m-secondary: #c7c7cc;
|
|
174
|
+
--m-muted: #98989d;
|
|
175
|
+
--m-success: #30d158;
|
|
176
|
+
--m-warning: #ffd60a;
|
|
177
|
+
--m-danger: #ff6961;
|
|
178
|
+
--m-info: #5aa9ff;
|
|
179
|
+
--m-on-feedback: #000000;
|
|
180
|
+
--m-code-bg: #0e0e10;
|
|
181
|
+
--m-code-line: rgb(255 255 255 / 0.1);
|
|
182
|
+
--m-float: none;
|
|
183
|
+
--m-swatch-ring: rgb(255 255 255 / 0.24);
|
|
184
|
+
--m-primary: var(--m-brand-d-primary, #ffffff);
|
|
185
|
+
--m-primary-hover: var(
|
|
186
|
+
--m-brand-d-primary-hover,
|
|
187
|
+
color-mix(in oklab, var(--m-primary) 85%, var(--m-ink))
|
|
188
|
+
);
|
|
189
|
+
--m-primary-active: var(
|
|
190
|
+
--m-brand-d-primary-active,
|
|
191
|
+
color-mix(in oklab, var(--m-primary) 72%, var(--m-ink))
|
|
192
|
+
);
|
|
193
|
+
--m-on-primary: var(--m-brand-d-on-primary, #000000);
|
|
194
|
+
--m-accent: var(--m-brand-d-accent, var(--m-primary));
|
|
195
|
+
--m-on-accent: var(--m-brand-d-on-accent, var(--m-on-primary));
|
|
196
|
+
--m-accent-fill: var(
|
|
197
|
+
--m-brand-d-accent-gradient,
|
|
198
|
+
linear-gradient(var(--m-accent), var(--m-accent))
|
|
199
|
+
);
|
|
200
|
+
--m-focus: var(--m-brand-d-focus, var(--m-primary));
|
|
201
|
+
--m-link: var(--m-brand-d-link, var(--m-ink));
|
|
202
|
+
--m-selected: var(
|
|
203
|
+
--m-brand-d-selected,
|
|
204
|
+
color-mix(in oklab, var(--m-primary) 10%, var(--m-paper))
|
|
205
|
+
);
|
|
206
|
+
--m-inv-color-scheme: light;
|
|
207
|
+
--m-inv-paper: var(--m-brand-l-paper, #f5f5f7);
|
|
208
|
+
--m-inv-surface: var(--m-brand-l-surface, #ffffff);
|
|
209
|
+
--m-inv-sunken: var(--m-brand-l-sunken, #ffffff);
|
|
210
|
+
--m-inv-line: #d1d1d6;
|
|
211
|
+
--m-inv-line-strong: #8b8b90;
|
|
212
|
+
--m-inv-ink: #000000;
|
|
213
|
+
--m-inv-secondary: #3a3a3c;
|
|
214
|
+
--m-inv-muted: #636366;
|
|
215
|
+
--m-inv-success: #1f7a36;
|
|
216
|
+
--m-inv-warning: #945700;
|
|
217
|
+
--m-inv-danger: #c70014;
|
|
218
|
+
--m-inv-info: #0060c7;
|
|
219
|
+
--m-inv-on-feedback: #ffffff;
|
|
220
|
+
--m-inv-primary: var(--m-brand-l-primary, #000000);
|
|
221
|
+
--m-inv-primary-hover: var(
|
|
222
|
+
--m-brand-l-primary-hover,
|
|
223
|
+
color-mix(in oklab, var(--m-inv-primary) 85%, var(--m-inv-ink))
|
|
224
|
+
);
|
|
225
|
+
--m-inv-primary-active: var(
|
|
226
|
+
--m-brand-l-primary-active,
|
|
227
|
+
color-mix(in oklab, var(--m-inv-primary) 72%, var(--m-inv-ink))
|
|
228
|
+
);
|
|
229
|
+
--m-inv-on-primary: var(--m-brand-l-on-primary, #ffffff);
|
|
230
|
+
--m-inv-accent: var(--m-brand-l-accent, var(--m-inv-primary));
|
|
231
|
+
--m-inv-on-accent: var(--m-brand-l-on-accent, var(--m-inv-on-primary));
|
|
232
|
+
--m-inv-accent-fill: var(
|
|
233
|
+
--m-brand-l-accent-gradient,
|
|
234
|
+
linear-gradient(var(--m-inv-accent), var(--m-inv-accent))
|
|
235
|
+
);
|
|
236
|
+
--m-inv-focus: var(--m-brand-l-focus, var(--m-inv-primary));
|
|
237
|
+
--m-inv-link: var(--m-brand-l-link, var(--m-inv-primary));
|
|
238
|
+
--m-inv-selected: var(
|
|
239
|
+
--m-brand-l-selected,
|
|
240
|
+
color-mix(in oklab, var(--m-inv-primary) 8%, var(--m-inv-paper))
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
/* Before a ThemeProvider writes data-mortar-appearance (server rendering, or
|
|
244
|
+
no JavaScript), follow the operating system so dark users see no light
|
|
245
|
+
flash. Set data-mortar-appearance="light" on the root to opt out. Keep this
|
|
246
|
+
block identical to the dark one above (tests/theming.test.mjs checks). */
|
|
247
|
+
@media (prefers-color-scheme: dark) {
|
|
248
|
+
:root:not([data-mortar-appearance]),
|
|
249
|
+
:root:not([data-mortar-appearance])
|
|
250
|
+
[data-mortar-brand]:not([data-mortar-appearance]) {
|
|
251
|
+
color-scheme: dark;
|
|
252
|
+
--m-paper: var(--m-brand-d-paper, #000000);
|
|
253
|
+
--m-surface: var(--m-brand-d-surface, #0e0e10);
|
|
254
|
+
--m-sunken: var(--m-brand-d-sunken, #1c1c1e);
|
|
255
|
+
--m-line: #29292c;
|
|
256
|
+
--m-line-strong: #727278;
|
|
257
|
+
--m-ink: #f5f5f7;
|
|
258
|
+
--m-secondary: #c7c7cc;
|
|
259
|
+
--m-muted: #98989d;
|
|
260
|
+
--m-success: #30d158;
|
|
261
|
+
--m-warning: #ffd60a;
|
|
262
|
+
--m-danger: #ff6961;
|
|
263
|
+
--m-info: #5aa9ff;
|
|
264
|
+
--m-on-feedback: #000000;
|
|
265
|
+
--m-code-bg: #0e0e10;
|
|
266
|
+
--m-code-line: rgb(255 255 255 / 0.1);
|
|
267
|
+
--m-float: none;
|
|
268
|
+
--m-swatch-ring: rgb(255 255 255 / 0.24);
|
|
269
|
+
--m-primary: var(--m-brand-d-primary, #ffffff);
|
|
270
|
+
--m-primary-hover: var(
|
|
271
|
+
--m-brand-d-primary-hover,
|
|
272
|
+
color-mix(in oklab, var(--m-primary) 85%, var(--m-ink))
|
|
273
|
+
);
|
|
274
|
+
--m-primary-active: var(
|
|
275
|
+
--m-brand-d-primary-active,
|
|
276
|
+
color-mix(in oklab, var(--m-primary) 72%, var(--m-ink))
|
|
277
|
+
);
|
|
278
|
+
--m-on-primary: var(--m-brand-d-on-primary, #000000);
|
|
279
|
+
--m-accent: var(--m-brand-d-accent, var(--m-primary));
|
|
280
|
+
--m-on-accent: var(--m-brand-d-on-accent, var(--m-on-primary));
|
|
281
|
+
--m-accent-fill: var(
|
|
282
|
+
--m-brand-d-accent-gradient,
|
|
283
|
+
linear-gradient(var(--m-accent), var(--m-accent))
|
|
284
|
+
);
|
|
285
|
+
--m-focus: var(--m-brand-d-focus, var(--m-primary));
|
|
286
|
+
--m-link: var(--m-brand-d-link, var(--m-ink));
|
|
287
|
+
--m-selected: var(
|
|
288
|
+
--m-brand-d-selected,
|
|
289
|
+
color-mix(in oklab, var(--m-primary) 10%, var(--m-paper))
|
|
290
|
+
);
|
|
291
|
+
--m-inv-color-scheme: light;
|
|
292
|
+
--m-inv-paper: var(--m-brand-l-paper, #f5f5f7);
|
|
293
|
+
--m-inv-surface: var(--m-brand-l-surface, #ffffff);
|
|
294
|
+
--m-inv-sunken: var(--m-brand-l-sunken, #ffffff);
|
|
295
|
+
--m-inv-line: #d1d1d6;
|
|
296
|
+
--m-inv-line-strong: #8b8b90;
|
|
297
|
+
--m-inv-ink: #000000;
|
|
298
|
+
--m-inv-secondary: #3a3a3c;
|
|
299
|
+
--m-inv-muted: #636366;
|
|
300
|
+
--m-inv-success: #1f7a36;
|
|
301
|
+
--m-inv-warning: #945700;
|
|
302
|
+
--m-inv-danger: #c70014;
|
|
303
|
+
--m-inv-info: #0060c7;
|
|
304
|
+
--m-inv-on-feedback: #ffffff;
|
|
305
|
+
--m-inv-primary: var(--m-brand-l-primary, #000000);
|
|
306
|
+
--m-inv-primary-hover: var(
|
|
307
|
+
--m-brand-l-primary-hover,
|
|
308
|
+
color-mix(in oklab, var(--m-inv-primary) 85%, var(--m-inv-ink))
|
|
309
|
+
);
|
|
310
|
+
--m-inv-primary-active: var(
|
|
311
|
+
--m-brand-l-primary-active,
|
|
312
|
+
color-mix(in oklab, var(--m-inv-primary) 72%, var(--m-inv-ink))
|
|
313
|
+
);
|
|
314
|
+
--m-inv-on-primary: var(--m-brand-l-on-primary, #ffffff);
|
|
315
|
+
--m-inv-accent: var(--m-brand-l-accent, var(--m-inv-primary));
|
|
316
|
+
--m-inv-on-accent: var(--m-brand-l-on-accent, var(--m-inv-on-primary));
|
|
317
|
+
--m-inv-accent-fill: var(
|
|
318
|
+
--m-brand-l-accent-gradient,
|
|
319
|
+
linear-gradient(var(--m-inv-accent), var(--m-inv-accent))
|
|
320
|
+
);
|
|
321
|
+
--m-inv-focus: var(--m-brand-l-focus, var(--m-inv-primary));
|
|
322
|
+
--m-inv-link: var(--m-brand-l-link, var(--m-inv-primary));
|
|
323
|
+
--m-inv-selected: var(
|
|
324
|
+
--m-brand-l-selected,
|
|
325
|
+
color-mix(in oklab, var(--m-inv-primary) 8%, var(--m-inv-paper))
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
:root:not([data-mortar-appearance]) [data-mortar] {
|
|
329
|
+
color-scheme: dark;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* 3. Scales. Appearance-independent; override on :root or any container to
|
|
334
|
+
retheme shape and rhythm. Density adjusts the sizing scale below. */
|
|
335
|
+
:root {
|
|
336
|
+
--m-font:
|
|
337
|
+
-apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue",
|
|
338
|
+
sans-serif;
|
|
339
|
+
/* Headings and component titles. Unset by default, so they keep the font
|
|
340
|
+
they inherit (the body's --m-font); a brand's fonts.heading
|
|
341
|
+
(--m-brand-font-heading) wins over it. */
|
|
342
|
+
--m-font-heading: initial;
|
|
343
|
+
--m-mono: "SF Mono", ui-monospace, Menlo, monospace;
|
|
344
|
+
--m-weight-regular: 400;
|
|
345
|
+
--m-weight-medium: 500;
|
|
346
|
+
--m-weight-semibold: 600;
|
|
347
|
+
--m-weight-bold: 700;
|
|
348
|
+
--m-tracking-display: -0.04em;
|
|
349
|
+
--m-tracking-heading: -0.02em;
|
|
350
|
+
--m-tracking-body: normal;
|
|
351
|
+
--m-tracking-caps: 0.04em;
|
|
352
|
+
--m-leading-display: 1.1;
|
|
353
|
+
--m-leading-heading: 1.3;
|
|
354
|
+
--m-leading-body: 1.6;
|
|
355
|
+
--m-space-1: 4px;
|
|
356
|
+
--m-space-2: 8px;
|
|
357
|
+
--m-space-3: 12px;
|
|
358
|
+
--m-space-4: 16px;
|
|
359
|
+
--m-space-6: 24px;
|
|
360
|
+
--m-space-8: 32px;
|
|
361
|
+
--m-space-10: 40px;
|
|
362
|
+
--m-space-12: 48px;
|
|
363
|
+
--m-radius-xs: 2px;
|
|
364
|
+
--m-radius-sm: 4px;
|
|
365
|
+
--m-radius: 8px;
|
|
366
|
+
--m-radius-lg: 12px;
|
|
367
|
+
--m-radius-xl: 16px;
|
|
368
|
+
--m-radius-full: 999px;
|
|
369
|
+
--m-control: 36px;
|
|
370
|
+
--m-pad: 14px;
|
|
371
|
+
--m-font-size: 14px;
|
|
372
|
+
--m-row-pad: 14px;
|
|
373
|
+
--m-icon: 16px;
|
|
374
|
+
--m-focus-offset: 3px;
|
|
375
|
+
/* Minimum hit size: 0 for fine pointers, 44px for coarse pointers (below). */
|
|
376
|
+
--m-touch-target: 0px;
|
|
377
|
+
/* Stacking scale: sticky chrome < dialogs < popovers < toasts < skip link. */
|
|
378
|
+
--m-z-sticky: 30;
|
|
379
|
+
--m-z-overlay: 100;
|
|
380
|
+
--m-z-popover: 110;
|
|
381
|
+
--m-z-toast: 130;
|
|
382
|
+
--m-z-skip: 140;
|
|
383
|
+
}
|
|
384
|
+
[data-mortar-density="comfortable"] {
|
|
385
|
+
--m-control: 36px;
|
|
386
|
+
--m-pad: 14px;
|
|
387
|
+
--m-font-size: 14px;
|
|
388
|
+
--m-row-pad: 14px;
|
|
389
|
+
}
|
|
390
|
+
[data-mortar-density="compact"] {
|
|
391
|
+
--m-control: 30px;
|
|
392
|
+
--m-pad: 10px;
|
|
393
|
+
--m-font-size: 13px;
|
|
394
|
+
--m-row-pad: 10px;
|
|
395
|
+
}
|
|
396
|
+
[data-mortar-density="spacious"] {
|
|
397
|
+
--m-control: 44px;
|
|
398
|
+
--m-pad: 18px;
|
|
399
|
+
--m-font-size: 15px;
|
|
400
|
+
--m-row-pad: 18px;
|
|
401
|
+
}
|
|
402
|
+
@media (pointer: coarse) {
|
|
403
|
+
[data-mortar] {
|
|
404
|
+
--m-control: 44px;
|
|
405
|
+
--m-touch-target: 44px;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
/* Inverse tone: any Mortar section root with data-tone="inverse" (sections, CTA,
|
|
409
|
+
banner, hero, featured pricing plan, bento item) flips appearance locally. */
|
|
410
|
+
[data-tone="inverse"] {
|
|
411
|
+
color-scheme: var(--m-inv-color-scheme);
|
|
412
|
+
--m-line-strong: var(--m-inv-line-strong);
|
|
413
|
+
--m-primary-active: var(--m-inv-primary-active);
|
|
414
|
+
--m-selected: var(--m-inv-selected);
|
|
415
|
+
--m-success: var(--m-inv-success);
|
|
416
|
+
--m-warning: var(--m-inv-warning);
|
|
417
|
+
--m-info: var(--m-inv-info);
|
|
418
|
+
--m-danger: var(--m-inv-danger);
|
|
419
|
+
--m-on-feedback: var(--m-inv-on-feedback);
|
|
420
|
+
--m-paper: var(--m-inv-paper);
|
|
421
|
+
--m-surface: var(--m-inv-surface);
|
|
422
|
+
--m-sunken: var(--m-inv-sunken);
|
|
423
|
+
--m-line: var(--m-inv-line);
|
|
424
|
+
--m-ink: var(--m-inv-ink);
|
|
425
|
+
--m-secondary: var(--m-inv-secondary);
|
|
426
|
+
--m-muted: var(--m-inv-muted);
|
|
427
|
+
--m-primary: var(--m-inv-primary);
|
|
428
|
+
--m-primary-hover: var(--m-inv-primary-hover);
|
|
429
|
+
--m-on-primary: var(--m-inv-on-primary);
|
|
430
|
+
--m-accent: var(--m-inv-accent);
|
|
431
|
+
--m-on-accent: var(--m-inv-on-accent);
|
|
432
|
+
--m-accent-fill: var(--m-inv-accent-fill);
|
|
433
|
+
--m-focus: var(--m-inv-focus);
|
|
434
|
+
--m-link: var(--m-inv-link);
|
|
435
|
+
--m-band: var(--m-inv-paper);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/* Accent wash for the accent hover and active states: the on-accent colour
|
|
439
|
+
with its lightness flipped to 0 or 1, so the fill moves away from its text.
|
|
440
|
+
Declared wherever --m-on-accent changes (appearance, brand, inverse band).
|
|
441
|
+
Browsers without relative colours leave it unset and keep the plain fill. */
|
|
442
|
+
@supports (color: oklch(from white round(1 - l, 1) 0 0)) {
|
|
443
|
+
:root,
|
|
444
|
+
[data-mortar-appearance],
|
|
445
|
+
[data-mortar-brand],
|
|
446
|
+
[data-tone="inverse"] {
|
|
447
|
+
--m-accent-wash: oklch(from var(--m-on-accent) round(1 - l, 1) 0 0);
|
|
448
|
+
}
|
|
449
|
+
}
|