@hraness/design-kit 0.36.4 → 0.36.5
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/ARTICLE_COPY.md +2 -0
- package/MARKETING_PRESET.md +2 -0
- package/README.md +18 -2
- package/dist/browser/index.js +143 -11
- package/dist/{chunk-0s71p361.js → chunk-xa28y4fg.js} +1 -0
- package/dist/react/index.js +41 -16
- package/dist/react/server.js +1 -1
- package/dist/stylex-manifest.json +1 -1
- package/dist/stylex.css +28 -16
- package/package.json +3 -2
- package/portfolio-inventory.json +1 -1
- package/src/browser/index.ts +1 -0
- package/src/browser/marketing-header.ts +113 -0
- package/src/browser/sticky-offset.ts +24 -12
- package/src/react/design-palette.stylex.ts +2 -2
- package/src/react/product-marketing.stylex.ts +1 -0
- package/src/react/theme.stylex.ts +4 -4
package/dist/stylex.css
CHANGED
|
@@ -3066,10 +3066,6 @@
|
|
|
3066
3066
|
min-block-size: 2.75rem;
|
|
3067
3067
|
}
|
|
3068
3068
|
|
|
3069
|
-
.xd0akbl {
|
|
3070
|
-
min-block-size: 2rem;
|
|
3071
|
-
}
|
|
3072
|
-
|
|
3073
3069
|
.xo67i2s {
|
|
3074
3070
|
min-block-size: 3.25rem;
|
|
3075
3071
|
}
|
|
@@ -3090,12 +3086,16 @@
|
|
|
3090
3086
|
min-block-size: var(--hraness-marketing-header-action-height, 2rem);
|
|
3091
3087
|
}
|
|
3092
3088
|
|
|
3093
|
-
.
|
|
3094
|
-
min-block-size: var(--hraness-marketing-header-
|
|
3089
|
+
.x5c9nq0 {
|
|
3090
|
+
min-block-size: var(--hraness-marketing-header-control-target, 2rem);
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
.x5zky9q {
|
|
3094
|
+
min-block-size: var(--hraness-marketing-header-control-target, var(--interactive-target-compact, 2.75rem));
|
|
3095
3095
|
}
|
|
3096
3096
|
|
|
3097
|
-
.
|
|
3098
|
-
min-block-size: var(--
|
|
3097
|
+
.x1jqubh4 {
|
|
3098
|
+
min-block-size: var(--hraness-marketing-header-height, 2.75rem);
|
|
3099
3099
|
}
|
|
3100
3100
|
|
|
3101
3101
|
.x1j3ipif {
|
|
@@ -3114,10 +3114,6 @@
|
|
|
3114
3114
|
min-inline-size: 0;
|
|
3115
3115
|
}
|
|
3116
3116
|
|
|
3117
|
-
.x1o8ym9z {
|
|
3118
|
-
min-inline-size: 2rem;
|
|
3119
|
-
}
|
|
3120
|
-
|
|
3121
3117
|
.xze7o54 {
|
|
3122
3118
|
min-inline-size: 40rem;
|
|
3123
3119
|
}
|
|
@@ -3134,8 +3130,12 @@
|
|
|
3134
3130
|
min-inline-size: 9rem;
|
|
3135
3131
|
}
|
|
3136
3132
|
|
|
3137
|
-
.
|
|
3138
|
-
min-inline-size: var(--
|
|
3133
|
+
.xye2cm2 {
|
|
3134
|
+
min-inline-size: var(--hraness-marketing-header-control-target, 2rem);
|
|
3135
|
+
}
|
|
3136
|
+
|
|
3137
|
+
.xq5ipov {
|
|
3138
|
+
min-inline-size: var(--hraness-marketing-header-control-target, var(--interactive-target-compact, 2.75rem));
|
|
3139
3139
|
}
|
|
3140
3140
|
|
|
3141
3141
|
.xz1t8dp {
|
|
@@ -4202,15 +4202,23 @@
|
|
|
4202
4202
|
.xn27wch.xn27wch {
|
|
4203
4203
|
min-block-size: max(2.75rem,var(--hraness-marketing-header-action-height, 2rem));
|
|
4204
4204
|
}
|
|
4205
|
+
}
|
|
4206
|
+
|
|
4207
|
+
@media (pointer: coarse) {
|
|
4208
|
+
.xczs0xf.xczs0xf {
|
|
4209
|
+
min-block-size: max(3rem,var(--hraness-marketing-header-control-target, 3rem));
|
|
4210
|
+
}
|
|
4211
|
+
}
|
|
4205
4212
|
|
|
4213
|
+
@media (width <= 48rem) {
|
|
4206
4214
|
.x1l2grcz.x1l2grcz {
|
|
4207
4215
|
min-inline-size: 0;
|
|
4208
4216
|
}
|
|
4209
4217
|
}
|
|
4210
4218
|
|
|
4211
4219
|
@media (pointer: coarse) {
|
|
4212
|
-
.
|
|
4213
|
-
min-inline-size: 3rem;
|
|
4220
|
+
.x12c0uzw.x12c0uzw {
|
|
4221
|
+
min-inline-size: max(3rem,var(--hraness-marketing-header-control-target, 3rem));
|
|
4214
4222
|
}
|
|
4215
4223
|
}
|
|
4216
4224
|
|
|
@@ -5699,6 +5707,10 @@
|
|
|
5699
5707
|
--hraness-marketing-grid-columns: initial;
|
|
5700
5708
|
}
|
|
5701
5709
|
|
|
5710
|
+
.xlhppvv {
|
|
5711
|
+
--hraness-marketing-header-control-target: 2.75rem;
|
|
5712
|
+
}
|
|
5713
|
+
|
|
5702
5714
|
.xphms39 {
|
|
5703
5715
|
--hraness-marketing-pillar-columns: 1;
|
|
5704
5716
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hraness/design-kit",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.5",
|
|
4
4
|
"description": "React components and CSS for Hraness apps and product sites: application shells, marketing sections, charts, themes, effects, and syntax highlighting. Built on @hraness/ui.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -143,6 +143,7 @@
|
|
|
143
143
|
"src/browser/artifact-share.ts",
|
|
144
144
|
"src/browser/foil.ts",
|
|
145
145
|
"src/browser/index.ts",
|
|
146
|
+
"src/browser/marketing-header.ts",
|
|
146
147
|
"src/browser/status-field.ts",
|
|
147
148
|
"src/browser/status-page.ts",
|
|
148
149
|
"src/browser/sticky-offset.ts",
|
|
@@ -322,7 +323,7 @@
|
|
|
322
323
|
"test": "bun test --preload ./scripts/register-stylex-test-transform.ts ./src",
|
|
323
324
|
"browser:install": "bun ./node_modules/playwright-core/cli.js install chromium",
|
|
324
325
|
"test:browser": "bun run test:browser:marketing && bun run test:browser:rest",
|
|
325
|
-
"test:browser:marketing": "bun run ./scripts/product-marketing-browser.ts",
|
|
326
|
+
"test:browser:marketing": "bun run ./scripts/product-marketing-browser.ts && bun run ./scripts/marketing-header-browser.ts",
|
|
326
327
|
"test:browser:rest": "bun run ./scripts/site-shell-browser.ts && bun run ./scripts/palette-browser.ts && bun run ./scripts/gallery-browser.ts && bun run ./scripts/global-error-browser.ts && bun run ./scripts/security-delivery-browser.ts && bun run ./scripts/paper-theme-browser.ts && bun run ./scripts/product-marketing-preset-browser.ts && bun run ./scripts/lantern-material-browser.ts && bun run ./scripts/foil-browser.ts && bun run ./scripts/hero-light-browser.ts && bun run ./scripts/status-page-browser.ts && bun run ./scripts/platform-install-browser.ts && bun run ./scripts/mockups-browser.ts && bun run ./scripts/agent-setup-browser.ts",
|
|
327
328
|
"test:package": "bun run ./scripts/package-smoke.ts && bun run ./scripts/mockups-import.ts",
|
|
328
329
|
"kb:refresh": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell refresh --root kb",
|
package/portfolio-inventory.json
CHANGED
package/src/browser/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./artifact-share.js";
|
|
|
5
5
|
export * from "./design-palette.js";
|
|
6
6
|
export * from "./foil.js";
|
|
7
7
|
export * from "./hero-light.js";
|
|
8
|
+
export * from "./marketing-header.js";
|
|
8
9
|
export * from "./status-page.js";
|
|
9
10
|
export * from "./sticky-offset.js";
|
|
10
11
|
export * from "../palette-appearance.js";
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
export interface MarketingHeaderOptions {
|
|
2
|
+
readonly brandHref?: string;
|
|
3
|
+
readonly brandLabel?: string;
|
|
4
|
+
readonly brandMark?: string;
|
|
5
|
+
/** Fixed-theme and authentication pages may explicitly omit appearance. */
|
|
6
|
+
readonly appearance?: "required" | "omitted";
|
|
7
|
+
/** Turn off geometry only when inspecting an unrendered DOM in unit tests. */
|
|
8
|
+
readonly measure?: boolean;
|
|
9
|
+
/** Require hydrated sticky clearance to match the live header height. */
|
|
10
|
+
readonly stickyOffset?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface MarketingHeaderInspection {
|
|
14
|
+
readonly headerCount: number;
|
|
15
|
+
readonly appearanceCount: number;
|
|
16
|
+
readonly brandHref: string | null;
|
|
17
|
+
readonly brandLabel: string | null;
|
|
18
|
+
readonly brandMark: string | null;
|
|
19
|
+
readonly links: readonly Readonly<{ href: string; label: string }>[];
|
|
20
|
+
readonly problems: readonly string[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Inspect a complete public page, including article, documentation, and status
|
|
25
|
+
* routes. This read-only function is self-contained so browser runners can use
|
|
26
|
+
* `page.evaluate(inspectMarketingHeader, options)` without loading a test script.
|
|
27
|
+
*/
|
|
28
|
+
export function inspectMarketingHeader(
|
|
29
|
+
options: MarketingHeaderOptions = {},
|
|
30
|
+
document: Document = globalThis.document,
|
|
31
|
+
): MarketingHeaderInspection {
|
|
32
|
+
const problems: string[] = [];
|
|
33
|
+
const headers = document.querySelectorAll('header[data-hraness-marketing="header"], header.hraness-marketing-header, header.hraness-marketing-header-surface');
|
|
34
|
+
const appearances = document.querySelectorAll("[data-hraness-appearance-menu]");
|
|
35
|
+
const mains = document.querySelectorAll("main");
|
|
36
|
+
const header = headers[0];
|
|
37
|
+
if (headers.length !== 1) problems.push(`Expected one product header; found ${headers.length}.`);
|
|
38
|
+
if (mains.length !== 1) problems.push(`Expected one main landmark; found ${mains.length}.`);
|
|
39
|
+
const appearanceCount = options.appearance === "omitted" ? 0 : 1;
|
|
40
|
+
if (appearances.length !== appearanceCount) problems.push(`Expected ${appearanceCount} appearance controls; found ${appearances.length}.`);
|
|
41
|
+
|
|
42
|
+
const brand = header?.querySelector<HTMLAnchorElement>("a.hraness-marketing-header__brand");
|
|
43
|
+
const mark = brand?.querySelector(".hraness-foil-mark");
|
|
44
|
+
const image = mark?.querySelector("img");
|
|
45
|
+
const brandHref = brand?.getAttribute("href") ?? null;
|
|
46
|
+
const brandLabel = (brand?.getAttribute("aria-label") ?? brand?.textContent)?.trim() || null;
|
|
47
|
+
const brandMark = image?.getAttribute("src") ?? null;
|
|
48
|
+
const nav = header?.querySelector("nav.hraness-marketing-header__nav");
|
|
49
|
+
const links = [...(nav?.querySelectorAll("a[href]") ?? [])].map(link => ({
|
|
50
|
+
href: link.getAttribute("href") ?? "",
|
|
51
|
+
label: (link.getAttribute("aria-label") ?? link.textContent)?.trim() ?? "",
|
|
52
|
+
}));
|
|
53
|
+
if (header !== undefined) {
|
|
54
|
+
const main = mains[0];
|
|
55
|
+
if (main !== undefined && (main.contains(header) || header.contains(main) || !(header.compareDocumentPosition(main) & 4))) {
|
|
56
|
+
problems.push("The product header must precede and sit outside the main landmark.");
|
|
57
|
+
}
|
|
58
|
+
if (brandHref !== (options.brandHref ?? "/")) problems.push("The product home link is missing or points to a different page.");
|
|
59
|
+
if (brandLabel === null || (options.brandLabel !== undefined && brandLabel !== options.brandLabel)) problems.push("The product home link has a missing or inconsistent name.");
|
|
60
|
+
if (brand?.hasAttribute("data-foil") !== true || mark === null || mark === undefined || image === null || image === undefined || !mark.querySelector(".hraness-foil-mark__paint") || !brandMark) {
|
|
61
|
+
problems.push("The product home link is missing its foil mark and artwork fallback.");
|
|
62
|
+
} else if (options.brandMark !== undefined && brandMark !== options.brandMark) {
|
|
63
|
+
problems.push("The product header uses different mark artwork.");
|
|
64
|
+
}
|
|
65
|
+
if (!nav || !(nav.getAttribute("aria-label")?.trim() || nav.getAttribute("aria-labelledby")?.trim()) || links.length === 0 || links.some(link => !link.label)) {
|
|
66
|
+
problems.push("The product header needs a named navigation with readable links.");
|
|
67
|
+
}
|
|
68
|
+
const appearance = appearances[0];
|
|
69
|
+
const actions = header.querySelector(".hraness-marketing-header__actions");
|
|
70
|
+
if (appearanceCount === 1 && appearance !== undefined) {
|
|
71
|
+
if (!actions?.contains(appearance) || !actions.lastElementChild?.contains(appearance)) {
|
|
72
|
+
problems.push("Appearance must be the final product-header action.");
|
|
73
|
+
}
|
|
74
|
+
if (!appearance.querySelector(":scope > summary, :scope > button, button.hraness-design-theme-toggle__trigger")) problems.push("Appearance is missing its trigger.");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (options.measure !== false) {
|
|
78
|
+
const view = document.defaultView;
|
|
79
|
+
if (view === null) problems.push("Rendered header inspection requires a browser window.");
|
|
80
|
+
else {
|
|
81
|
+
const trigger = appearance?.querySelector(":scope > summary, :scope > button, button.hraness-design-theme-toggle__trigger");
|
|
82
|
+
for (const [name, element] of [["header", header], ["brand", brand], ["mark", mark], ["navigation", nav], ["appearance", appearanceCount === 1 ? appearance : null], ["appearance trigger", appearanceCount === 1 ? trigger : null]] as const) {
|
|
83
|
+
if (!element) continue;
|
|
84
|
+
const box = element.getBoundingClientRect();
|
|
85
|
+
let hidden = false;
|
|
86
|
+
for (let ancestor: Element | null = element; ancestor !== null; ancestor = ancestor.parentElement) {
|
|
87
|
+
const style = view.getComputedStyle(ancestor);
|
|
88
|
+
if (style.display === "none" || style.visibility === "hidden" || style.visibility === "collapse" || Number(style.opacity) === 0) hidden = true;
|
|
89
|
+
}
|
|
90
|
+
if (box.width <= 0 || box.height <= 0 || hidden) problems.push(`The product ${name} is not visible.`);
|
|
91
|
+
}
|
|
92
|
+
const box = header.getBoundingClientRect();
|
|
93
|
+
if (box.left < -1 || box.right > view.innerWidth + 1) problems.push("The product header extends outside the viewport.");
|
|
94
|
+
const inner = header.querySelector(".hraness-marketing-header__inner");
|
|
95
|
+
if (!inner || !["grid", "flex"].includes(view.getComputedStyle(inner).display)) problems.push("The shared product-header layout styles are missing.");
|
|
96
|
+
if (options.stickyOffset === true && view.getComputedStyle(header).position === "sticky") {
|
|
97
|
+
for (const target of [document.documentElement, mains[0]]) {
|
|
98
|
+
if (!target) continue;
|
|
99
|
+
const offset = Number.parseFloat(view.getComputedStyle(target).getPropertyValue("--hraness-sticky-offset"));
|
|
100
|
+
if (!Number.isFinite(offset) || Math.abs(offset - box.height) > 1) problems.push("Sticky clearance does not match the measured product header.");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (appearanceCount === 1 && trigger) {
|
|
104
|
+
const triggerBox = trigger.getBoundingClientRect();
|
|
105
|
+
if (triggerBox.width < 43.5 || triggerBox.height < 43.5) problems.push("The appearance trigger is smaller than 44px.");
|
|
106
|
+
const actionLinks = actions?.querySelectorAll("a[href]") ?? [];
|
|
107
|
+
if ([...actionLinks].some(link => link.getBoundingClientRect().right > triggerBox.right + 1)) problems.push("Appearance is not the rightmost header action.");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { headerCount: headers.length, appearanceCount: appearances.length, brandHref, brandLabel, brandMark, links, problems };
|
|
113
|
+
}
|
|
@@ -32,10 +32,13 @@ function resolveHeader(
|
|
|
32
32
|
return root.querySelector(stickyOffsetHeaderSelector);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function
|
|
36
|
-
if (target !== undefined) return target;
|
|
37
|
-
const
|
|
38
|
-
|
|
35
|
+
function resolveTargets(header: Element, target: HTMLElement | undefined): readonly HTMLElement[] {
|
|
36
|
+
if (target !== undefined) return [target];
|
|
37
|
+
const targets = new Set<HTMLElement>([header.ownerDocument.documentElement]);
|
|
38
|
+
for (let ancestor: Element | null = header; ancestor !== null; ancestor = ancestor.parentElement) {
|
|
39
|
+
if (ancestor.matches(".hraness-marketing-page, [data-hraness-marketing-preset]")) targets.add(ancestor as HTMLElement);
|
|
40
|
+
}
|
|
41
|
+
return [...targets];
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
/** Border-box height of sticky marketing chrome, as a CSS length. */
|
|
@@ -43,10 +46,10 @@ export function measureStickyOffset(header: Element): string {
|
|
|
43
46
|
return `${header.getBoundingClientRect().height}px`;
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
/**
|
|
49
|
+
/** Publish on the document and enclosing page/preset scopes so local defaults cannot mask the measurement. */
|
|
47
50
|
export function publishStickyOffset(header: Element, target?: HTMLElement): string {
|
|
48
51
|
const value = measureStickyOffset(header);
|
|
49
|
-
|
|
52
|
+
for (const destination of resolveTargets(header, target)) destination.style.setProperty(stickyOffsetCustomProperty, value);
|
|
50
53
|
return value;
|
|
51
54
|
}
|
|
52
55
|
|
|
@@ -62,21 +65,30 @@ export function syncStickyOffset(options: StickyOffsetSyncOptions = {}): () => v
|
|
|
62
65
|
const root = options.root ?? document;
|
|
63
66
|
const header = resolveHeader(root, options.header);
|
|
64
67
|
if (header === null) return () => {};
|
|
65
|
-
const
|
|
68
|
+
const targets = resolveTargets(header, options.target);
|
|
69
|
+
const prior = targets.map(target => ({ target, value: target.style.getPropertyValue(stickyOffsetCustomProperty), priority: typeof target.style.getPropertyPriority === "function" ? target.style.getPropertyPriority(stickyOffsetCustomProperty) : "" }));
|
|
70
|
+
let published: string;
|
|
66
71
|
const publish = () => {
|
|
67
|
-
|
|
72
|
+
published = measureStickyOffset(header);
|
|
73
|
+
for (const target of targets) target.style.setProperty(stickyOffsetCustomProperty, published);
|
|
74
|
+
};
|
|
75
|
+
const restore = () => {
|
|
76
|
+
for (const { target, value, priority } of prior) {
|
|
77
|
+
if (target.style.getPropertyValue(stickyOffsetCustomProperty) !== published
|
|
78
|
+
|| (typeof target.style.getPropertyPriority === "function" && target.style.getPropertyPriority(stickyOffsetCustomProperty) !== "")) continue;
|
|
79
|
+
if (value) target.style.setProperty(stickyOffsetCustomProperty, value, priority);
|
|
80
|
+
else target.style.removeProperty(stickyOffsetCustomProperty);
|
|
81
|
+
}
|
|
68
82
|
};
|
|
69
83
|
publish();
|
|
70
84
|
const view = document.defaultView;
|
|
71
85
|
if (view === null || typeof view.ResizeObserver !== "function") {
|
|
72
|
-
return
|
|
73
|
-
target.style.removeProperty(stickyOffsetCustomProperty);
|
|
74
|
-
};
|
|
86
|
+
return restore;
|
|
75
87
|
}
|
|
76
88
|
const observer = new view.ResizeObserver(publish);
|
|
77
89
|
observer.observe(header);
|
|
78
90
|
return () => {
|
|
79
91
|
observer.disconnect();
|
|
80
|
-
|
|
92
|
+
restore();
|
|
81
93
|
};
|
|
82
94
|
}
|
|
@@ -38,8 +38,8 @@ export const paletteMenuStyles = stylex.create({
|
|
|
38
38
|
display: "inline-flex",
|
|
39
39
|
justifyContent: "center",
|
|
40
40
|
listStyleType: "none",
|
|
41
|
-
"min-block-size": "var(--interactive-target-compact, 2.75rem)",
|
|
42
|
-
"min-inline-size": "var(--interactive-target-compact, 2.75rem)",
|
|
41
|
+
"min-block-size": "var(--hraness-marketing-header-control-target, var(--interactive-target-compact, 2.75rem))",
|
|
42
|
+
"min-inline-size": "var(--hraness-marketing-header-control-target, var(--interactive-target-compact, 2.75rem))",
|
|
43
43
|
outlineColor: "var(--hraness-material-focus, var(--focus, Highlight))",
|
|
44
44
|
outlineOffset: 3,
|
|
45
45
|
paddingBlock: "0.5rem",
|
|
@@ -88,6 +88,7 @@ export const marketingStyles = stylex.create({
|
|
|
88
88
|
"-webkit-font-smoothing": "antialiased"
|
|
89
89
|
},
|
|
90
90
|
"header": {
|
|
91
|
+
"--hraness-marketing-header-control-target": "2.75rem",
|
|
91
92
|
"--hraness-sticky-offset": "calc(var(--hraness-marketing-header-height, 2.75rem) + 1px)",
|
|
92
93
|
"color": {
|
|
93
94
|
"default": "var(--hraness-marketing-ink)",
|
|
@@ -226,12 +226,12 @@ export const themeStyles = stylex.create({
|
|
|
226
226
|
},
|
|
227
227
|
lineHeight: "inherit",
|
|
228
228
|
"min-block-size": {
|
|
229
|
-
default: "2rem",
|
|
230
|
-
[coarsePointer]: "3rem",
|
|
229
|
+
default: "var(--hraness-marketing-header-control-target, 2rem)",
|
|
230
|
+
[coarsePointer]: "max(3rem, var(--hraness-marketing-header-control-target, 3rem))",
|
|
231
231
|
},
|
|
232
232
|
"min-inline-size": {
|
|
233
|
-
default: "2rem",
|
|
234
|
-
[coarsePointer]: "3rem",
|
|
233
|
+
default: "var(--hraness-marketing-header-control-target, 2rem)",
|
|
234
|
+
[coarsePointer]: "max(3rem, var(--hraness-marketing-header-control-target, 3rem))",
|
|
235
235
|
},
|
|
236
236
|
opacity: {
|
|
237
237
|
default: null,
|