@gemboss/gem-framework 0.15.0 → 0.18.11
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 +107 -3
- package/dist/SOURCE.json +3 -3
- package/dist/editions.d.ts +9 -0
- package/dist/editions.js +24 -0
- package/dist/gem-framework.css +16 -7
- package/dist/index.js +233 -38
- package/dist/primitives.css +12 -3
- package/dist/section-gate.js +107 -30
- package/dist/sections.css +4 -4
- package/dist/sections.js +122 -12
- package/dist/settings-schema.js +70 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19,6 +19,137 @@ function gemPartClass(part) {
|
|
|
19
19
|
return GEM_PART_CLASS[part] ?? null;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// ../../packages/gem-framework/src/section-dividers.ts
|
|
23
|
+
var spikes = (() => {
|
|
24
|
+
const teeth = [];
|
|
25
|
+
for (let x = 95; x > 0; x -= 5) teeth.push(`L${x} ${teeth.length % 2 === 0 ? 10 : 3}`);
|
|
26
|
+
return `M0 0 H100 V3 ${teeth.join(" ")} L0 ${teeth.length % 2 === 0 ? 10 : 3} Z`;
|
|
27
|
+
})();
|
|
28
|
+
var GEM_SECTION_DIVIDER_PATHS = Object.freeze({
|
|
29
|
+
wave: "M0 0 H100 V3 C80 9 70 -1 50 4 C30 9 20 1 0 4 Z",
|
|
30
|
+
slope: "M0 0 H100 V10 Z",
|
|
31
|
+
spikes,
|
|
32
|
+
arch: "M0 0 H100 V2 Q50 12 0 2 Z",
|
|
33
|
+
blob: "M0 0 H100 V4 C85 11 72 0 58 5 C44 10 30 2 16 6 C10 8 5 5 0 6 Z"
|
|
34
|
+
});
|
|
35
|
+
function gemSectionDividers(props) {
|
|
36
|
+
const layers = [];
|
|
37
|
+
for (const edge of ["top", "bottom"]) {
|
|
38
|
+
const shape = props?.[`divider_${edge}`];
|
|
39
|
+
if (typeof shape === "string" && Object.hasOwn(GEM_SECTION_DIVIDER_PATHS, shape)) {
|
|
40
|
+
const known = shape;
|
|
41
|
+
layers.push({ edge, shape: known, path: GEM_SECTION_DIVIDER_PATHS[known] });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return layers;
|
|
45
|
+
}
|
|
46
|
+
function height(value) {
|
|
47
|
+
if (typeof value !== "number" && typeof value !== "string") return void 0;
|
|
48
|
+
if (typeof value === "string" && !/^\d+(?:\.\d+)?$/.test(value.trim())) return void 0;
|
|
49
|
+
const n = Number(value);
|
|
50
|
+
return Number.isFinite(n) && n >= 0 && n <= 320 ? n : void 0;
|
|
51
|
+
}
|
|
52
|
+
var NAMED_COLORS = /* @__PURE__ */ new Set([
|
|
53
|
+
"transparent",
|
|
54
|
+
"currentcolor",
|
|
55
|
+
"inherit",
|
|
56
|
+
"initial",
|
|
57
|
+
"unset",
|
|
58
|
+
"black",
|
|
59
|
+
"silver",
|
|
60
|
+
"gray",
|
|
61
|
+
"grey",
|
|
62
|
+
"white",
|
|
63
|
+
"maroon",
|
|
64
|
+
"red",
|
|
65
|
+
"purple",
|
|
66
|
+
"fuchsia",
|
|
67
|
+
"green",
|
|
68
|
+
"lime",
|
|
69
|
+
"olive",
|
|
70
|
+
"yellow",
|
|
71
|
+
"navy",
|
|
72
|
+
"blue",
|
|
73
|
+
"teal",
|
|
74
|
+
"aqua",
|
|
75
|
+
"orange"
|
|
76
|
+
]);
|
|
77
|
+
var NUMBER = "[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?";
|
|
78
|
+
var CHANNEL = new RegExp(`^${NUMBER}%?$`, "i");
|
|
79
|
+
var PERCENT = new RegExp(`^${NUMBER}%$`, "i");
|
|
80
|
+
var ANGLE = new RegExp(`^${NUMBER}(?:deg|grad|rad|turn)?$`, "i");
|
|
81
|
+
var finite = (value) => Number.isFinite(Number.parseFloat(value));
|
|
82
|
+
var numeric = (value) => CHANNEL.test(value) && finite(value);
|
|
83
|
+
var percentage = (value) => PERCENT.test(value) && finite(value);
|
|
84
|
+
var angle = (value) => ANGLE.test(value) && finite(value);
|
|
85
|
+
function functionalColor(value) {
|
|
86
|
+
const match = /^(rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch)\(([^()]*)\)$/i.exec(value);
|
|
87
|
+
if (!match) return false;
|
|
88
|
+
const name = match[1].toLowerCase(), body = match[2].trim();
|
|
89
|
+
let channels, alpha;
|
|
90
|
+
if (body.includes(",")) {
|
|
91
|
+
if (!["rgb", "rgba", "hsl", "hsla"].includes(name) || body.includes("/")) return false;
|
|
92
|
+
const parts = body.split(",").map((part) => part.trim());
|
|
93
|
+
if (parts.length !== 3 && parts.length !== 4) return false;
|
|
94
|
+
channels = parts.slice(0, 3);
|
|
95
|
+
alpha = parts[3];
|
|
96
|
+
if ((name === "rgb" || name === "rgba") && new Set(channels.map((part) => part.endsWith("%"))).size !== 1) return false;
|
|
97
|
+
} else {
|
|
98
|
+
const parts = body.split("/");
|
|
99
|
+
if (parts.length > 2) return false;
|
|
100
|
+
channels = parts[0].trim().split(/\s+/);
|
|
101
|
+
alpha = parts[1]?.trim();
|
|
102
|
+
}
|
|
103
|
+
if (channels.length !== 3 || alpha !== void 0 && !numeric(alpha)) return false;
|
|
104
|
+
if (name === "rgb" || name === "rgba") return channels.every(numeric);
|
|
105
|
+
if (name === "hsl" || name === "hsla" || name === "hwb") {
|
|
106
|
+
return angle(channels[0]) && percentage(channels[1]) && percentage(channels[2]);
|
|
107
|
+
}
|
|
108
|
+
if (name === "lch" || name === "oklch") return numeric(channels[0]) && numeric(channels[1]) && angle(channels[2]);
|
|
109
|
+
return channels.every(numeric);
|
|
110
|
+
}
|
|
111
|
+
function color(value) {
|
|
112
|
+
if (typeof value !== "string") return void 0;
|
|
113
|
+
const v = value.trim();
|
|
114
|
+
if (!v || v.length > 128 || /[;{}<>\\]/.test(v)) return void 0;
|
|
115
|
+
if (/^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(v) || NAMED_COLORS.has(v.toLowerCase())) return v;
|
|
116
|
+
if (functionalColor(v)) return v;
|
|
117
|
+
const token = /^var\(\s*--[A-Za-z0-9_-]+\s*(?:,\s*([^()]*))?\)$/.exec(v);
|
|
118
|
+
if (token && (token[1] === void 0 || color(token[1]))) return v;
|
|
119
|
+
return void 0;
|
|
120
|
+
}
|
|
121
|
+
function gemSectionDividerStyle(props, bandBackground) {
|
|
122
|
+
if (!gemSectionDividers(props).length) return {};
|
|
123
|
+
const value = props?.divider_flip;
|
|
124
|
+
const flip = value === true || value === "true" || value === 1 || value === "1";
|
|
125
|
+
return {
|
|
126
|
+
"--gem-element-divider-height": `${height(props?.divider_height) ?? 48}px`,
|
|
127
|
+
"--gem-element-divider-color": color(props?.divider_color) ?? color(bandBackground) ?? "var(--gem-section-bg, var(--gem-color-background))",
|
|
128
|
+
"--gem-element-divider-scale-x": flip ? "-1" : "1"
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function gemSectionDividerResponsiveStyle(props) {
|
|
132
|
+
const n = height(props?.divider_height);
|
|
133
|
+
return n === void 0 ? {} : { "--gem-element-divider-height": `${n}px` };
|
|
134
|
+
}
|
|
135
|
+
var GEM_ELEMENT_SECTION_DIVIDER_CSS = [
|
|
136
|
+
".gem-el-section[data-gem-element-dividers] { position: relative; }",
|
|
137
|
+
// A configured edge must escape the band's parallax clip. The media keeps its own clipped
|
|
138
|
+
// wrapper so releasing the root cannot expose the deliberately oversized moving background.
|
|
139
|
+
".gem-el-section[data-gem-parallax][data-gem-element-dividers] { overflow: visible; isolation: auto; }",
|
|
140
|
+
".gem-el-section[data-gem-element-dividers] > .gem-el-section__parallax-clip { position: absolute; inset: 0; overflow: hidden; border-radius: inherit; pointer-events: none; z-index: 0; }",
|
|
141
|
+
// Edge paint may extend into a neighbour with little padding. Only content, never its background,
|
|
142
|
+
// stacks above it. Guard on the current document's opted-in markup: a retained CSS resource after
|
|
143
|
+
// navigation must not change a page with no native dividers.
|
|
144
|
+
// An ordinary neighbouring parallax band also isolates its content by default. Release that
|
|
145
|
+
// stacking context on divider documents, retaining its existing media clip and direct markup.
|
|
146
|
+
"body:has(.gem-el-section[data-gem-element-dividers]) .gem-el-section[data-gem-parallax] { isolation: auto; }",
|
|
147
|
+
"body:has(.gem-el-section[data-gem-element-dividers]) .gem-el-section > .gem-el-section__inner { position: relative; z-index: 2; }",
|
|
148
|
+
".gem-el-section > .gem-el-section__divider { position: absolute; display: block; inset-inline: 0; width: 100%; max-width: none; height: var(--gem-element-divider-height, 48px); color: var(--gem-element-divider-color, var(--gem-color-background)); overflow: hidden; pointer-events: none; z-index: 1; transform: scaleX(var(--gem-element-divider-scale-x, 1)); }",
|
|
149
|
+
".gem-el-section > .gem-el-section__divider--bottom { top: 100%; }",
|
|
150
|
+
".gem-el-section > .gem-el-section__divider--top { bottom: 100%; transform: scaleX(var(--gem-element-divider-scale-x, 1)) scaleY(-1); }"
|
|
151
|
+
].join("\n");
|
|
152
|
+
|
|
22
153
|
// ../../packages/gem-framework/src/form-set.ts
|
|
23
154
|
var GEM_FORM_TOKEN_KEYS = [
|
|
24
155
|
"radius",
|
|
@@ -76,7 +207,7 @@ var GEM_FORM_DEFAULTS = {
|
|
|
76
207
|
checkboxAccent: "var(--gem-color-accent)",
|
|
77
208
|
checkboxSize: "24px"
|
|
78
209
|
};
|
|
79
|
-
var GEM_FORM_VAR_SCOPE = "[data-gem-form-set], [data-gem-form-set] :is(input, select, textarea, button, form)";
|
|
210
|
+
var GEM_FORM_VAR_SCOPE = "[data-gem-form-set], [data-gem-form-set] :is(input, select, textarea, button, form, output)";
|
|
80
211
|
function gemFormCssBlock(form) {
|
|
81
212
|
const vars = gemFormCssVars(form);
|
|
82
213
|
return vars.length ? `${GEM_FORM_VAR_SCOPE} {
|
|
@@ -130,6 +261,30 @@ var GEM_FORM_SETS = [
|
|
|
130
261
|
}
|
|
131
262
|
];
|
|
132
263
|
var gemFormSetsFor = (posture) => GEM_FORM_SETS.filter((s) => s.postures.includes(posture));
|
|
264
|
+
var GEM_SOFT_FIELD_FAMILIES = ["natural", "beauty", "home", "food"];
|
|
265
|
+
function deriveFormSetId(source) {
|
|
266
|
+
const norm = (v) => typeof v === "string" ? v.trim().toLowerCase() : "";
|
|
267
|
+
const radius = norm(source?.global_settings?.button_radius);
|
|
268
|
+
const style = norm(source?.global_settings?.button_style);
|
|
269
|
+
if (radius === "sharp" && style === "outline") return "hairline-underline";
|
|
270
|
+
if (radius === "pill" && style !== "soft") return "pill-joined";
|
|
271
|
+
if (style === "soft" || GEM_SOFT_FIELD_FAMILIES.includes(norm(source?.family))) return "soft-filled";
|
|
272
|
+
return "crisp-outline";
|
|
273
|
+
}
|
|
274
|
+
function gemPlanFormSet(plan) {
|
|
275
|
+
const tokens = plan?.tokens;
|
|
276
|
+
if (tokens && typeof tokens === "object" && Object.prototype.hasOwnProperty.call(tokens, "form")) {
|
|
277
|
+
const own = tokens.form;
|
|
278
|
+
if (own === null) return null;
|
|
279
|
+
if (own && typeof own === "object" && !Array.isArray(own)) {
|
|
280
|
+
if (hasForm(own)) return own;
|
|
281
|
+
const byId = GEM_FORM_SETS.find((s) => s.id === own.id);
|
|
282
|
+
if (byId) return { ...byId.form };
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const set = GEM_FORM_SETS.find((s) => s.id === deriveFormSetId({ family: plan?.style_pack?.family, global_settings: plan?.global_settings }));
|
|
286
|
+
return set ? { ...set.form } : null;
|
|
287
|
+
}
|
|
133
288
|
|
|
134
289
|
// ../../packages/gem-framework/src/plan-shape.ts
|
|
135
290
|
function gemStyleSpaceFor(plan) {
|
|
@@ -230,13 +385,13 @@ function mixHex(from, to, t) {
|
|
|
230
385
|
const channel = (x, y) => Math.round(x * (1 - t) + y * t).toString(16).padStart(2, "0");
|
|
231
386
|
return `#${channel(a.r, b.r)}${channel(a.g, b.g)}${channel(a.b, b.b)}`;
|
|
232
387
|
}
|
|
233
|
-
function aaTextColor(
|
|
234
|
-
const from = normalizeHex(
|
|
388
|
+
function aaTextColor(color2, backgrounds, min = MIN_TEXT_CONTRAST) {
|
|
389
|
+
const from = normalizeHex(color2);
|
|
235
390
|
const bgs = backgrounds.map(normalizeHex).filter((bg) => Boolean(bg));
|
|
236
|
-
if (!from || !bgs.length) return
|
|
391
|
+
if (!from || !bgs.length) return color2;
|
|
237
392
|
const worst = (c) => Math.min(...bgs.map((bg) => hexContrastRatio(c, bg)));
|
|
238
|
-
let best = { color, score: worst(from) };
|
|
239
|
-
if (best.score >= min) return
|
|
393
|
+
let best = { color: color2, score: worst(from) };
|
|
394
|
+
if (best.score >= min) return color2;
|
|
240
395
|
let pass;
|
|
241
396
|
for (const toward of ["#000000", "#ffffff"]) {
|
|
242
397
|
for (let step = 1; step <= 50; step++) {
|
|
@@ -280,7 +435,7 @@ function gemButtonGradientEndCss(accent = "var(--gem-color-accent)", accentText
|
|
|
280
435
|
}
|
|
281
436
|
|
|
282
437
|
// ../../packages/gem-framework/src/tokens.ts
|
|
283
|
-
var gemFrameworkVersion = "0.
|
|
438
|
+
var gemFrameworkVersion = "0.18.11";
|
|
284
439
|
var GEM_FOCUS_RING_CSS_VAR = "--gem-focus-ring: 2px solid var(--gem-color-accent);";
|
|
285
440
|
var GEM_TAP_MIN_CSS_VAR = "--gem-tap-min: 44px;";
|
|
286
441
|
var GEM_FOCUS_OFFSET_CSS_VAR = "--gem-focus-offset: 3px;";
|
|
@@ -443,17 +598,17 @@ function gemBandScheme(c, band) {
|
|
|
443
598
|
danger: aaTextColor(c.danger, grounds)
|
|
444
599
|
};
|
|
445
600
|
}
|
|
446
|
-
function gemBandSchemeColors(
|
|
601
|
+
function gemBandSchemeColors(color2 = {}) {
|
|
447
602
|
const c = Object.fromEntries(
|
|
448
603
|
requiredGemTokenKeys.color.map((key) => {
|
|
449
|
-
const value =
|
|
604
|
+
const value = color2?.[key];
|
|
450
605
|
return [key, typeof value === "string" && value.trim() ? stripImportant(value) : defaultGemTokens.color[key]];
|
|
451
606
|
})
|
|
452
607
|
);
|
|
453
608
|
return { dark: gemBandScheme(c, "dark"), accent: gemBandScheme(c, "accent") };
|
|
454
609
|
}
|
|
455
|
-
function gemBandSchemeCssVars(
|
|
456
|
-
const schemes = gemBandSchemeColors(
|
|
610
|
+
function gemBandSchemeCssVars(color2 = {}) {
|
|
611
|
+
const schemes = gemBandSchemeColors(color2);
|
|
457
612
|
return GEM_BAND_SCHEMES.flatMap(
|
|
458
613
|
(band) => requiredGemTokenKeys.color.map((key) => `--gem-scheme-${band}-${slugify(key)}: ${schemes[band][key]};`)
|
|
459
614
|
);
|
|
@@ -749,12 +904,12 @@ function gemMobileTokenCssVars(tokens, phone = readPhoneTokens(tokens)) {
|
|
|
749
904
|
var rampKey = (k) => k.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
750
905
|
var isRampKey = (k) => GEM_TYPE_RAMP_KEYS.some((r) => rampKey(r) === rampKey(k));
|
|
751
906
|
var LENGTH = /^\d*\.?\d+(px|rem|em)$/;
|
|
752
|
-
var
|
|
907
|
+
var NUMBER2 = /^\d*\.?\d+$/;
|
|
753
908
|
var typeRampValue = (typography, key) => {
|
|
754
909
|
const hit = Object.entries(typography ?? {}).find(([k]) => rampKey(k) === rampKey(key));
|
|
755
910
|
const v = hit == null || hit[1] == null ? "" : stripImportant(hit[1]).trim();
|
|
756
911
|
if (!v) return null;
|
|
757
|
-
return (key === "scale" ?
|
|
912
|
+
return (key === "scale" ? NUMBER2.test(v) && Number(v) > 0 : LENGTH.test(v)) ? v : null;
|
|
758
913
|
};
|
|
759
914
|
var GEM_TYPE_MOBILE_MAX = "749px";
|
|
760
915
|
function gemTypeRampCssVars(typography) {
|
|
@@ -833,6 +988,14 @@ var GEM_EDITION_SUPPORT_MONTHS = 6;
|
|
|
833
988
|
var EDITION_2_CSS = [
|
|
834
989
|
`:where(&) { ${GEM_HEADING_SIZE_CSS_VARS.filter((decl) => !decl.startsWith("--gem-section-heading-size-mobile") && !decl.startsWith("--gem-hero-heading-size-mobile")).join(" ")} }`
|
|
835
990
|
];
|
|
991
|
+
var EDITION_3_ELEMENTS = [
|
|
992
|
+
`:where(&) .gem-product-card-grid--quick-view-grid .gem-product-card-grid__card { border: 0; border-radius: 0; box-shadow: none; background: transparent; padding: 0; }`,
|
|
993
|
+
`:where(&) .gem-product-card-grid--quick-view-grid .gem-product-card__media > .gem-product-card__badges { display: flex; }`,
|
|
994
|
+
`@media (max-width: 989px) { :where(&) .gem-product-card-grid--quick-view-grid .gem-product-card-grid__grid[data-gem-product-grid] { grid-template-columns: repeat(var(--gem-product-card-grid-mobile-columns, 2), minmax(0, 1fr)); } }`,
|
|
995
|
+
`:where(&) .gem-hero.gem-hero-banner--compact-collection .gem-hero__overlay:not(.has-media) { position: relative; inset: auto; z-index: auto; opacity: 1; width: min(var(--gem-layout-page, 1200px), calc(100% - var(--gem-layout-gutter, 32px))); margin: clamp(24px, 5vw, 48px) auto 0; background: none; color: var(--gem-color-text); border-radius: 0; }`,
|
|
996
|
+
`:where(&) .gem-hero.gem-hero-banner--compact-collection .gem-hero__overlay:not(.has-media) .gem-hero__heading { color: var(--gem-color-text); }`,
|
|
997
|
+
`:where(&) .gem-section.gem-hero.gem-hero-banner--compact-collection:not(:has(> .gem-hero__bg)) { padding-block-end: 0; }`
|
|
998
|
+
];
|
|
836
999
|
var GEM_FRAMEWORK_EDITIONS = [
|
|
837
1000
|
{ edition: 1, since: "0.1.0", released: "2026-07-04", changes: [], css: [] },
|
|
838
1001
|
{
|
|
@@ -841,6 +1004,18 @@ var GEM_FRAMEWORK_EDITIONS = [
|
|
|
841
1004
|
released: "2026-10-10",
|
|
842
1005
|
changes: ["Section headings and hero titles follow your type scale on tablets and computers. Phones keep their current size."],
|
|
843
1006
|
css: EDITION_2_CSS
|
|
1007
|
+
},
|
|
1008
|
+
{
|
|
1009
|
+
// Edition 3. Collection pages at Dawn's tiers (12/10/2026, measured on a "Start from scratch" theme): EDITION_3_ELEMENTS.
|
|
1010
|
+
edition: 3,
|
|
1011
|
+
since: "0.17.0",
|
|
1012
|
+
released: "2026-10-12",
|
|
1013
|
+
changes: [
|
|
1014
|
+
"Collection grids: each product photo fills its column, phones and tablets show your mobile column count, and Sale and Sold out badges appear.",
|
|
1015
|
+
"The collection title sits on the page, lined up with the products, in your text colour."
|
|
1016
|
+
],
|
|
1017
|
+
css: [],
|
|
1018
|
+
elements: EDITION_3_ELEMENTS
|
|
844
1019
|
}
|
|
845
1020
|
];
|
|
846
1021
|
var LATEST_GEM_FRAMEWORK_EDITION = GEM_FRAMEWORK_EDITIONS[GEM_FRAMEWORK_EDITIONS.length - 1].edition;
|
|
@@ -862,6 +1037,9 @@ function addEditionSupportMonths(released) {
|
|
|
862
1037
|
function gemFrameworkEditionScope(edition) {
|
|
863
1038
|
return GEM_FRAMEWORK_EDITIONS.filter((e) => e.edition >= edition).map((e) => `[data-gem-edition='${e.edition}']`).join(", ");
|
|
864
1039
|
}
|
|
1040
|
+
function gemFrameworkEditionElementCss() {
|
|
1041
|
+
return GEM_FRAMEWORK_EDITIONS.flatMap((e) => (e.elements ?? []).map((rule) => rule.replaceAll("&", gemFrameworkEditionScope(e.edition)))).join("\n");
|
|
1042
|
+
}
|
|
865
1043
|
function gemFrameworkEditionCss() {
|
|
866
1044
|
return GEM_FRAMEWORK_EDITIONS.flatMap((e) => e.css.map((rule) => rule.replaceAll("&", gemFrameworkEditionScope(e.edition)))).join("\n");
|
|
867
1045
|
}
|
|
@@ -1425,18 +1603,8 @@ var GEM_POPUP_SHELL_CSS = GEM_POPUP_SHELL_CSS_LINES.join("\n");
|
|
|
1425
1603
|
|
|
1426
1604
|
// ../../packages/gem-framework/src/primitives.ts
|
|
1427
1605
|
var dividerMask = (path) => `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='${path}'/%3E%3C/svg%3E")`;
|
|
1428
|
-
var
|
|
1429
|
-
|
|
1430
|
-
for (let x = 95; x > 0; x -= 5) teeth.push(`L${x} ${teeth.length % 2 === 0 ? 10 : 3}`);
|
|
1431
|
-
return `M0 0 H100 V3 ${teeth.join(" ")} L0 ${teeth.length % 2 === 0 ? 10 : 3} Z`;
|
|
1432
|
-
})();
|
|
1433
|
-
var DIVIDER_SHAPES = {
|
|
1434
|
-
wave: "M0 0 H100 V3 C80 9 70 -1 50 4 C30 9 20 1 0 4 Z",
|
|
1435
|
-
slope: "M0 0 H100 V10 Z",
|
|
1436
|
-
spikes: spikePath,
|
|
1437
|
-
arch: "M0 0 H100 V2 Q50 12 0 2 Z",
|
|
1438
|
-
blob: "M0 0 H100 V4 C85 11 72 0 58 5 C44 10 30 2 16 6 C10 8 5 5 0 6 Z"
|
|
1439
|
-
};
|
|
1606
|
+
var knownValues = (attr, values) => `:where(${values.map((v) => `[${attr}='${v}']`).join(", ")})`;
|
|
1607
|
+
var DIVIDER_SHAPES = Object.keys(GEM_SECTION_DIVIDER_PATHS);
|
|
1440
1608
|
var GEM_DIVIDER_CSS_LINES = [
|
|
1441
1609
|
// The clip is WIDENED, not removed. `.gem-section` sets `overflow: clip` and the wedge is drawn
|
|
1442
1610
|
// at `top: 100%` / `bottom: 100%` — entirely outside the box — so the parent deleted every
|
|
@@ -1447,7 +1615,8 @@ var GEM_DIVIDER_CSS_LINES = [
|
|
|
1447
1615
|
// it entirely would paint square corners over that radius. A browser without
|
|
1448
1616
|
// `overflow-clip-margin` keeps plain `clip` — the divider stays hidden, which is today's
|
|
1449
1617
|
// behaviour rather than a broken layout.
|
|
1450
|
-
|
|
1618
|
+
// Only for a shape that has a mask (knownValues): a "none" edge used to widen the clip by 48px for nothing.
|
|
1619
|
+
`:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top]${knownValues("data-gem-divider-top", DIVIDER_SHAPES)}, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom]${knownValues("data-gem-divider-bottom", DIVIDER_SHAPES)} { position: relative; overflow: clip; overflow-clip-margin: var(--gem-divider-height, 48px); }`,
|
|
1451
1620
|
// Shared geometry. `top: 100%` / `bottom: 100%` put it outside the box; z-index 1 keeps it above the
|
|
1452
1621
|
// neighbouring band's background. pointer-events: none so it never eats a click near the seam.
|
|
1453
1622
|
// Qualified by SHAPE. Unqualified, any value paints a solid 48px slab — including the literal
|
|
@@ -1457,7 +1626,7 @@ var GEM_DIVIDER_CSS_LINES = [
|
|
|
1457
1626
|
":is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom]::after { top: 100%; }",
|
|
1458
1627
|
// The top edge reuses the same masks, mirrored, so five shapes cover both edges.
|
|
1459
1628
|
":is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top]::before { bottom: 100%; transform: scaleY(-1); }",
|
|
1460
|
-
...Object.entries(
|
|
1629
|
+
...Object.entries(GEM_SECTION_DIVIDER_PATHS).flatMap(([name, path]) => {
|
|
1461
1630
|
const mask = dividerMask(path);
|
|
1462
1631
|
return [
|
|
1463
1632
|
`:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom='${name}']::after { -webkit-mask-image: ${mask}; mask-image: ${mask}; }`,
|
|
@@ -1466,8 +1635,10 @@ var GEM_DIVIDER_CSS_LINES = [
|
|
|
1466
1635
|
})
|
|
1467
1636
|
];
|
|
1468
1637
|
var GEM_DIVIDER_CSS = GEM_DIVIDER_CSS_LINES.join("\n");
|
|
1638
|
+
var GEM_CARD_STYLES = ["outline", "shadow", "filled"];
|
|
1469
1639
|
var GEM_CARD_CSS_LINES = [
|
|
1470
|
-
|
|
1640
|
+
// Only for a style that draws (knownValues): "none", the knob's revert value, arrives here as an attribute too.
|
|
1641
|
+
`:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-card]${knownValues("data-gem-card", GEM_CARD_STYLES)} :is(.gem-section__inner, [class*='__inner']) { border-radius: var(--gem-radius-md); padding: var(--gem-space-xl); }`,
|
|
1471
1642
|
":is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-card='outline'] :is(.gem-section__inner, [class*='__inner']) { border: 1px solid var(--gem-color-border); }",
|
|
1472
1643
|
":is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-card='shadow'] :is(.gem-section__inner, [class*='__inner']) { background: var(--gem-color-surface); box-shadow: var(--gem-shadow-md); }",
|
|
1473
1644
|
// `filled` tints the section's own ground rather than reaching for a fixed colour, so it stays
|
|
@@ -1761,7 +1932,7 @@ function createGemBaseCssParts(profile) {
|
|
|
1761
1932
|
].join("\n");
|
|
1762
1933
|
return {
|
|
1763
1934
|
// Edition rules close the primitives (editions.ts): custom properties on <html>, scoped :where([data-gem-edition]).
|
|
1764
|
-
primitives: [reset, "", createPrimitiveCss(), "", gemFrameworkEditionCss(), "", ""].join("\n"),
|
|
1935
|
+
primitives: [reset, "", createPrimitiveCss(), "", gemFrameworkEditionElementCss(), "", gemFrameworkEditionCss(), "", ""].join("\n"),
|
|
1765
1936
|
sections: [createShellCss(), "", createSectionCss(), "", createThemeProfileCss(profile)].join("\n")
|
|
1766
1937
|
};
|
|
1767
1938
|
}
|
|
@@ -1771,7 +1942,11 @@ function createThemeProfileCss(profile = "dawn-parity") {
|
|
|
1771
1942
|
function createMorphProfileCss() {
|
|
1772
1943
|
return [
|
|
1773
1944
|
"/* Gem morph profile: style packs and section presets provide visual transformation above core primitives. */",
|
|
1774
|
-
":root { --gem-profile-mode: morph; }"
|
|
1945
|
+
":root { --gem-profile-mode: morph; }",
|
|
1946
|
+
// A morph theme's quick-view card is a box drawn from its card tokens (the .gem-card primitive). Edition 3 unboxes this
|
|
1947
|
+
// card for Dawn's collection page; restated here one class higher, so a morph theme keeps its box and its card knobs on
|
|
1948
|
+
// every edition (review of #764). The same values as .gem-card: nothing changes for a morph store on edition 1 or 2.
|
|
1949
|
+
".gem-product-card-grid--quick-view-grid .gem-card.gem-product-card-grid__card { border: var(--gem-border-subtle, 1px solid var(--gem-color-border)); border-radius: var(--gem-card-radius, var(--gem-radius-md)); background: var(--gem-card-background, var(--gem-color-surface)); padding: var(--gem-component-card-padding, var(--gem-space-md)); box-shadow: var(--gem-shadow-sm, none); }"
|
|
1775
1950
|
].join("\n");
|
|
1776
1951
|
}
|
|
1777
1952
|
function createPrimitiveCss() {
|
|
@@ -2217,17 +2392,25 @@ function createPrimitiveCss() {
|
|
|
2217
2392
|
// .gem-rating above is a type rule for a text label; every actual star row in the theme was a
|
|
2218
2393
|
// hardcoded five-glyph literal, so a captured 4-of-5 (or a half star) had nowhere to land. The
|
|
2219
2394
|
// fill is a percentage-width overlay, so fractional values render exactly instead of rounding.
|
|
2395
|
+
// SVG stars (GemFactory gap #45, 0.18.11): real review widgets draw each star as an SVG (solid + outline), and the
|
|
2396
|
+
// eight product-reviews sections rebuilt in GemFactory put those SVGs in __base / __fill. Two things broke the fill
|
|
2397
|
+
// (measured 12/10/2026): the base `svg { max-width: 100% }` shrank the SVGs in the clipped __fill to the fill's
|
|
2398
|
+
// width (4.2 drew as five squeezed stars), and a .gem-stars that is a stretched grid / flex item computed its
|
|
2399
|
+
// percentage against the stretched width (3 of 5 drew as 5). The row is as wide as its stars, always, and a star
|
|
2400
|
+
// keeps its own size inside the clip.
|
|
2220
2401
|
".gem-stars {",
|
|
2221
2402
|
" --gem-stars-total: 5;",
|
|
2222
2403
|
" --gem-stars-value: 5;",
|
|
2223
2404
|
" position: relative;",
|
|
2224
2405
|
" display: inline-block;",
|
|
2406
|
+
" width: max-content;",
|
|
2225
2407
|
" line-height: 1;",
|
|
2226
2408
|
" font-size: var(--gem-text-sm, 0.8125rem);",
|
|
2227
2409
|
" letter-spacing: 0.1em;",
|
|
2228
2410
|
" color: var(--gem-color-border);",
|
|
2229
2411
|
"}",
|
|
2230
2412
|
".gem-stars__base, .gem-stars__fill { display: block; white-space: nowrap; }",
|
|
2413
|
+
".gem-stars :is(svg, img) { max-width: none; flex: none; }",
|
|
2231
2414
|
".gem-stars__fill {",
|
|
2232
2415
|
" position: absolute;",
|
|
2233
2416
|
" inset: 0;",
|
|
@@ -3733,7 +3916,7 @@ function createDawnParityCss() {
|
|
|
3733
3916
|
".gem-card, .gem-product-card { border: 0; border-radius: 0; box-shadow: none; background: transparent; padding: 0; }",
|
|
3734
3917
|
".gem-product-card__media, .gem-media { border: 0; border-radius: 0; box-shadow: none; background: rgb(244 244 244); }",
|
|
3735
3918
|
".gem-product-card__media { display: block; position: relative; width: 100%; height: 0; min-block-size: 0; padding-bottom: 100%; aspect-ratio: auto; overflow: hidden; }",
|
|
3736
|
-
".gem-featured-collection--editorial-grid .gem-product-card__media, .gem-product-card-grid--quick-view-grid .gem-product-card__media, .gem-main-search .gem-product-card__media, .gem-cart-recommendations--dawn-empty .gem-product-card__media { min-block-size: 0 !important; }",
|
|
3919
|
+
".gem-featured-collection--editorial-grid .gem-product-card__media, .gem-product-card-grid--quick-view-grid .gem-product-card__media, .gem-main-search .gem-product-card__media, .gem-cart-recommendations--dawn-empty .gem-product-card__media, .gem-recommended-products--product-rail .gem-product-card__media, .gem-cart-recommendations--product-rail .gem-product-card__media { min-block-size: 0 !important; }",
|
|
3737
3920
|
".gem-product-card__media > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }",
|
|
3738
3921
|
// Home product grids show generated/lifestyle imagery (not catalog product-on-white shots), so
|
|
3739
3922
|
// `contain` letterboxes them inside the square card (looks misaligned / floating off the box).
|
|
@@ -3750,7 +3933,7 @@ function createDawnParityCss() {
|
|
|
3750
3933
|
".gem-cart-recommendations--dawn-empty .gem-product-card__quick-actions { display: none; }",
|
|
3751
3934
|
".gem-featured-collection--editorial-grid > .gem-section__inner > .gem-section__heading, .gem-featured-collection--editorial-grid > .gem-section__inner > .gem-section__body { display: none; }",
|
|
3752
3935
|
".gem-featured-collection--editorial-grid { padding-block: 28px 36px; }",
|
|
3753
|
-
".gem-featured-collection--editorial-grid .gem-section__grid, .gem-product-card-grid--quick-view-grid .gem-section__grid, .gem-main-search .gem-section__grid { grid-template-columns: repeat(var(--gem-product-card-grid-columns, 4), minmax(0, 1fr)); gap: 8px; }",
|
|
3936
|
+
".gem-featured-collection--editorial-grid .gem-section__grid, .gem-product-card-grid--quick-view-grid .gem-section__grid, .gem-main-search .gem-section__grid, .gem-recommended-products--product-rail .gem-section__grid, .gem-cart-recommendations--product-rail .gem-section__grid { grid-template-columns: repeat(var(--gem-product-card-grid-columns, 4), minmax(0, 1fr)); gap: 8px; }",
|
|
3754
3937
|
".gem-product-card-grid--quick-view-grid { padding-top: 0; }",
|
|
3755
3938
|
".gem-product-card-grid--quick-view-grid .gem-section__heading:empty { display: none; }",
|
|
3756
3939
|
// Hide a compare-at only when the price ISN'T actually on sale. The rule used to hide it
|
|
@@ -3920,14 +4103,16 @@ function createDawnParityMobileCss() {
|
|
|
3920
4103
|
" .gem-hero-banner--compact-collection { padding-block: 25px; }",
|
|
3921
4104
|
" .gem-hero-banner--compact-collection .gem-section__heading { font-size: 30px; line-height: 39px; }",
|
|
3922
4105
|
" .gem-product-card-grid--quick-view-grid > .gem-section__inner, .gem-main-search > .gem-section__inner { width: calc(100% - 30px); }",
|
|
3923
|
-
|
|
4106
|
+
// 8px on a phone too, as the featured collection and the two product rails: the cards are Dawn's flat cards, and with
|
|
4107
|
+
// no padding of their own a 4px gap left two columns of titles 4px apart at 320 (review of gemsite #951).
|
|
4108
|
+
" .gem-product-card-grid--quick-view-grid .gem-product-card-grid__grid { gap: 8px !important; }",
|
|
3924
4109
|
" .gem-product-card__content { padding-top: 8px; gap: 4px; }",
|
|
3925
4110
|
" .gem-product-card__title { font-size: 15px; line-height: 24px; }",
|
|
3926
4111
|
" .gem-product-card__price, .gem-product-card__price .gem-price { font-size: 16px; line-height: 24px; }",
|
|
3927
4112
|
// Fallback = the profile's own phone heading, declared once as --gem-heading-phone-cap on the :root above.
|
|
3928
4113
|
" .gem-section__heading { font-size: var(--gem-section-heading-size-mobile, var(--gem-heading-phone-cap)); }",
|
|
3929
4114
|
" .gem-hero-banner h1, .gem-hero-banner h2 { font-size: var(--gem-hero-heading-size-mobile, var(--gem-heading-phone-cap)); }",
|
|
3930
|
-
" .gem-featured-collection--editorial-grid .gem-section__grid, .gem-product-card-grid--quick-view-grid .gem-section__grid, .gem-main-search .gem-section__grid { grid-template-columns: repeat(var(--gem-product-card-grid-mobile-columns, 2), minmax(0, 1fr)); }",
|
|
4115
|
+
" .gem-featured-collection--editorial-grid .gem-section__grid, .gem-product-card-grid--quick-view-grid .gem-section__grid, .gem-main-search .gem-section__grid, .gem-recommended-products--product-rail .gem-section__grid, .gem-cart-recommendations--product-rail .gem-section__grid { grid-template-columns: repeat(var(--gem-product-card-grid-mobile-columns, 2), minmax(0, 1fr)); }",
|
|
3931
4116
|
" .gem-product-main[data-gem-product-main-layout='dawn-main'] > .gem-section__inner { width: calc(100% - 30px); }",
|
|
3932
4117
|
" .gem-product-main[data-gem-product-main-layout='dawn-main'] .gem-product-media-gallery__frame { display: flex; gap: 0; overflow-x: auto; scroll-snap-type: x mandatory; }",
|
|
3933
4118
|
" .gem-product-main[data-gem-product-main-layout='dawn-main'] .gem-product-media-gallery__item { flex: 0 0 100%; scroll-snap-align: start; aspect-ratio: 1 / 1; }",
|
|
@@ -6344,7 +6529,8 @@ var PREVIEW_MEDIA_CSS = [
|
|
|
6344
6529
|
function renderGemPreviewDocument(plan, options = {}) {
|
|
6345
6530
|
const page = options.page ?? "home";
|
|
6346
6531
|
const profile = plan.theme_profile ?? "dawn-parity";
|
|
6347
|
-
const
|
|
6532
|
+
const formSet = gemPlanFormSet(plan);
|
|
6533
|
+
const baseCss = createGemThemeCss({ ...plan.tokens, form: formSet ?? void 0 }, ":root", { profile, ...gemPlanShapeKnobs(plan) });
|
|
6348
6534
|
const overflowGuardCss = "html,body{max-width:100%;overflow-x:hidden}*,*::before,*::after{box-sizing:border-box}";
|
|
6349
6535
|
const css = [baseCss, overflowGuardCss, CHROME_VARIANT_CSS, options.sectionCss, PREVIEW_MEDIA_CSS].filter(Boolean).join("\n");
|
|
6350
6536
|
const runtimeJs = options.includeRuntime === false ? "" : createGemRuntimeBootstrap(planToRuntimeBootstrapConfig(plan));
|
|
@@ -6352,7 +6538,7 @@ function renderGemPreviewDocument(plan, options = {}) {
|
|
|
6352
6538
|
const footer = renderGemShellFooter(plan);
|
|
6353
6539
|
const sectionsHtml = renderGemPageSections(plan, page, options.sectionMarkup ?? {});
|
|
6354
6540
|
const title = options.title ?? `${plan.name} preview`;
|
|
6355
|
-
const formAttrs = Object.entries(gemFormAttributes(
|
|
6541
|
+
const formAttrs = Object.entries(gemFormAttributes(formSet ?? void 0)).map(([k, v]) => ` ${k}="${escapeAttribute(v)}"`).join("");
|
|
6356
6542
|
const bodyClass = ["gem-theme", `gem-theme--${slugify(profile)}`, options.bodyClassName].filter(Boolean).join(" ");
|
|
6357
6543
|
const edition = gemFrameworkEditionOf(plan.framework_edition);
|
|
6358
6544
|
const editionAttr = edition > 1 ? ` data-gem-edition="${edition}"` : "";
|
|
@@ -6590,7 +6776,7 @@ function renderGemSectionMarkup(section) {
|
|
|
6590
6776
|
const widthRaw = settings.gem_content_width;
|
|
6591
6777
|
const width = widthRaw === "full" || widthRaw === "contained" || widthRaw === "narrow" ? widthRaw : "";
|
|
6592
6778
|
const heightRaw = settings.gem_section_height;
|
|
6593
|
-
const
|
|
6779
|
+
const height2 = heightRaw === "short" || heightRaw === "normal" || heightRaw === "tall" ? heightRaw : "";
|
|
6594
6780
|
const columnsRaw = settings.gem_grid_columns;
|
|
6595
6781
|
const columns = columnsRaw === "2" || columnsRaw === "3" || columnsRaw === "4" ? columnsRaw : "";
|
|
6596
6782
|
const bgRaw = settings.gem_section_background;
|
|
@@ -6615,7 +6801,7 @@ function renderGemSectionMarkup(section) {
|
|
|
6615
6801
|
media ? ` data-gem-media-position="${media}"` : "",
|
|
6616
6802
|
spacing ? ` data-gem-content-spacing="${spacing}"` : "",
|
|
6617
6803
|
width ? ` data-gem-content-width="${width}"` : "",
|
|
6618
|
-
|
|
6804
|
+
height2 ? ` data-gem-section-height="${height2}"` : "",
|
|
6619
6805
|
columns ? ` data-gem-grid-columns="${columns}"` : "",
|
|
6620
6806
|
background ? ` data-gem-section-background="${background}"` : "",
|
|
6621
6807
|
priceColor ? ` data-gem-price-color="${priceColor}"` : "",
|
|
@@ -7422,6 +7608,7 @@ export {
|
|
|
7422
7608
|
GEM_BUTTON_TOKEN_SHAPES,
|
|
7423
7609
|
GEM_COUNTDOWN_ENDED_CSS,
|
|
7424
7610
|
GEM_EDITION_SUPPORT_MONTHS,
|
|
7611
|
+
GEM_ELEMENT_SECTION_DIVIDER_CSS,
|
|
7425
7612
|
GEM_FIELD_JOINS,
|
|
7426
7613
|
GEM_FIELD_SHAPES,
|
|
7427
7614
|
GEM_FORM_CSS_VARIABLES,
|
|
@@ -7444,6 +7631,8 @@ export {
|
|
|
7444
7631
|
GEM_ROW_CSS,
|
|
7445
7632
|
GEM_ROW_CSS_VARIABLES,
|
|
7446
7633
|
GEM_ROW_GAP_CSS,
|
|
7634
|
+
GEM_SECTION_DIVIDER_PATHS,
|
|
7635
|
+
GEM_SOFT_FIELD_FAMILIES,
|
|
7447
7636
|
LATEST_GEM_FRAMEWORK_EDITION,
|
|
7448
7637
|
MIN_TEXT_CONTRAST,
|
|
7449
7638
|
MODERN_MINERAL_FAMILY_PACK_ID,
|
|
@@ -7473,6 +7662,7 @@ export {
|
|
|
7473
7662
|
createThemeProfileCss,
|
|
7474
7663
|
defaultGemTokens,
|
|
7475
7664
|
defaultSelection,
|
|
7665
|
+
deriveFormSetId,
|
|
7476
7666
|
gemBandSchemeColors,
|
|
7477
7667
|
gemBandSchemeCssVars,
|
|
7478
7668
|
gemBandSchemeDeclarations,
|
|
@@ -7484,6 +7674,7 @@ export {
|
|
|
7484
7674
|
gemFormCssVars,
|
|
7485
7675
|
gemFormSetsFor,
|
|
7486
7676
|
gemFrameworkEditionCss,
|
|
7677
|
+
gemFrameworkEditionElementCss,
|
|
7487
7678
|
gemFrameworkEditionOf,
|
|
7488
7679
|
gemFrameworkEditionScope,
|
|
7489
7680
|
gemFrameworkEditionSupportedUntil,
|
|
@@ -7495,9 +7686,13 @@ export {
|
|
|
7495
7686
|
gemMotionScaleCssVars,
|
|
7496
7687
|
gemPartClass,
|
|
7497
7688
|
gemPhoneTokenTarget,
|
|
7689
|
+
gemPlanFormSet,
|
|
7498
7690
|
gemPlanShapeKnobs,
|
|
7499
7691
|
gemRuntimePluginModuleKeys,
|
|
7500
7692
|
gemRuntimePluginSources,
|
|
7693
|
+
gemSectionDividerResponsiveStyle,
|
|
7694
|
+
gemSectionDividerStyle,
|
|
7695
|
+
gemSectionDividers,
|
|
7501
7696
|
getGemFrameworkValidationRule,
|
|
7502
7697
|
hexContrastRatio,
|
|
7503
7698
|
hexRelativeLuminance,
|
package/dist/primitives.css
CHANGED
|
@@ -495,12 +495,14 @@ a {
|
|
|
495
495
|
--gem-stars-value: 5;
|
|
496
496
|
position: relative;
|
|
497
497
|
display: inline-block;
|
|
498
|
+
width: max-content;
|
|
498
499
|
line-height: 1;
|
|
499
500
|
font-size: var(--gem-text-sm, 0.8125rem);
|
|
500
501
|
letter-spacing: 0.1em;
|
|
501
502
|
color: var(--gem-color-border);
|
|
502
503
|
}
|
|
503
504
|
.gem-stars__base, .gem-stars__fill { display: block; white-space: nowrap; }
|
|
505
|
+
.gem-stars :is(svg, img) { max-width: none; flex: none; }
|
|
504
506
|
.gem-stars__fill {
|
|
505
507
|
position: absolute;
|
|
506
508
|
inset: 0;
|
|
@@ -1051,7 +1053,7 @@ a {
|
|
|
1051
1053
|
[data-gem-ambient] { --gem-ambient-amp: 2px; animation-duration: 12s; }
|
|
1052
1054
|
[data-gem-reveal] { transition: none; opacity: 1; transform: none; }
|
|
1053
1055
|
}
|
|
1054
|
-
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top], :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom] { position: relative; overflow: clip; overflow-clip-margin: var(--gem-divider-height, 48px); }
|
|
1056
|
+
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top]:where([data-gem-divider-top='wave'], [data-gem-divider-top='slope'], [data-gem-divider-top='spikes'], [data-gem-divider-top='arch'], [data-gem-divider-top='blob']), :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom]:where([data-gem-divider-bottom='wave'], [data-gem-divider-bottom='slope'], [data-gem-divider-bottom='spikes'], [data-gem-divider-bottom='arch'], [data-gem-divider-bottom='blob']) { position: relative; overflow: clip; overflow-clip-margin: var(--gem-divider-height, 48px); }
|
|
1055
1057
|
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom='wave']::after, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom='slope']::after, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom='spikes']::after, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom='arch']::after, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom='blob']::after, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top='wave']::before, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top='slope']::before, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top='spikes']::before, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top='arch']::before, :is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top='blob']::before { content: ''; position: absolute; left: 0; right: 0; z-index: 1; pointer-events: none; height: var(--gem-divider-height, 48px); background: var(--gem-section-bg, var(--gem-color-background)); -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-size: 100% 100%; mask-size: 100% 100%; }
|
|
1056
1058
|
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom]::after { top: 100%; }
|
|
1057
1059
|
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top]::before { bottom: 100%; transform: scaleY(-1); }
|
|
@@ -1065,7 +1067,7 @@ a {
|
|
|
1065
1067
|
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top='arch']::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M0 0 H100 V2 Q50 12 0 2 Z'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M0 0 H100 V2 Q50 12 0 2 Z'/%3E%3C/svg%3E"); }
|
|
1066
1068
|
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-bottom='blob']::after { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M0 0 H100 V4 C85 11 72 0 58 5 C44 10 30 2 16 6 C10 8 5 5 0 6 Z'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M0 0 H100 V4 C85 11 72 0 58 5 C44 10 30 2 16 6 C10 8 5 5 0 6 Z'/%3E%3C/svg%3E"); }
|
|
1067
1069
|
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-divider-top='blob']::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M0 0 H100 V4 C85 11 72 0 58 5 C44 10 30 2 16 6 C10 8 5 5 0 6 Z'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M0 0 H100 V4 C85 11 72 0 58 5 C44 10 30 2 16 6 C10 8 5 5 0 6 Z'/%3E%3C/svg%3E"); }
|
|
1068
|
-
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-card] :is(.gem-section__inner, [class*='__inner']) { border-radius: var(--gem-radius-md); padding: var(--gem-space-xl); }
|
|
1070
|
+
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-card]:where([data-gem-card='outline'], [data-gem-card='shadow'], [data-gem-card='filled']) :is(.gem-section__inner, [class*='__inner']) { border-radius: var(--gem-radius-md); padding: var(--gem-space-xl); }
|
|
1069
1071
|
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-card='outline'] :is(.gem-section__inner, [class*='__inner']) { border: 1px solid var(--gem-color-border); }
|
|
1070
1072
|
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-card='shadow'] :is(.gem-section__inner, [class*='__inner']) { background: var(--gem-color-surface); box-shadow: var(--gem-shadow-md); }
|
|
1071
1073
|
:is(.gem-section, .gem-hero, .gem-hero-split, .gem-hero-collage, .gem-hero-triptych, .gem-slideshow)[data-gem-card='filled'] :is(.gem-section__inner, [class*='__inner']) { background: color-mix(in srgb, currentColor 6%, transparent); }
|
|
@@ -1435,5 +1437,12 @@ a {
|
|
|
1435
1437
|
.gem-collection-filter-toolbar__active-filter, .gem-collection-filter-toolbar__clear { min-height: 2.25rem; align-items: center; }
|
|
1436
1438
|
}
|
|
1437
1439
|
|
|
1438
|
-
:where([data-gem-edition='
|
|
1440
|
+
:where([data-gem-edition='3']) .gem-product-card-grid--quick-view-grid .gem-product-card-grid__card { border: 0; border-radius: 0; box-shadow: none; background: transparent; padding: 0; }
|
|
1441
|
+
:where([data-gem-edition='3']) .gem-product-card-grid--quick-view-grid .gem-product-card__media > .gem-product-card__badges { display: flex; }
|
|
1442
|
+
@media (max-width: 989px) { :where([data-gem-edition='3']) .gem-product-card-grid--quick-view-grid .gem-product-card-grid__grid[data-gem-product-grid] { grid-template-columns: repeat(var(--gem-product-card-grid-mobile-columns, 2), minmax(0, 1fr)); } }
|
|
1443
|
+
:where([data-gem-edition='3']) .gem-hero.gem-hero-banner--compact-collection .gem-hero__overlay:not(.has-media) { position: relative; inset: auto; z-index: auto; opacity: 1; width: min(var(--gem-layout-page, 1200px), calc(100% - var(--gem-layout-gutter, 32px))); margin: clamp(24px, 5vw, 48px) auto 0; background: none; color: var(--gem-color-text); border-radius: 0; }
|
|
1444
|
+
:where([data-gem-edition='3']) .gem-hero.gem-hero-banner--compact-collection .gem-hero__overlay:not(.has-media) .gem-hero__heading { color: var(--gem-color-text); }
|
|
1445
|
+
:where([data-gem-edition='3']) .gem-section.gem-hero.gem-hero-banner--compact-collection:not(:has(> .gem-hero__bg)) { padding-block-end: 0; }
|
|
1446
|
+
|
|
1447
|
+
:where([data-gem-edition='2'], [data-gem-edition='3']) { --gem-section-heading-size: calc(var(--gem-h2) * var(--gem-typography-heading-scale, 1)); --gem-hero-heading-size: calc(var(--gem-h1) * var(--gem-typography-heading-scale, 1)); }
|
|
1439
1448
|
|