@gemboss/gem-framework 0.6.0 → 0.9.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.
Files changed (57) hide show
  1. package/README.md +63 -1
  2. package/dist/SOURCE.json +2 -2
  3. package/dist/gem-framework.css +206 -147
  4. package/dist/gem-runtime.js +93 -15
  5. package/dist/index.js +629 -178
  6. package/dist/plugins/before_after.d.ts +9 -0
  7. package/dist/plugins/before_after.js +37 -0
  8. package/dist/plugins/carousel.d.ts +9 -0
  9. package/dist/plugins/carousel.js +49 -0
  10. package/dist/plugins/cart-drawer.d.ts +9 -0
  11. package/dist/plugins/cart-drawer.js +69 -0
  12. package/dist/plugins/context-adapter.d.ts +9 -0
  13. package/dist/plugins/context-adapter.js +17 -0
  14. package/dist/plugins/countdown.d.ts +9 -0
  15. package/dist/plugins/countdown.js +164 -0
  16. package/dist/plugins/disclosure.d.ts +9 -0
  17. package/dist/plugins/disclosure.js +40 -0
  18. package/dist/plugins/hero-slideshow.d.ts +9 -0
  19. package/dist/plugins/hero-slideshow.js +57 -0
  20. package/dist/plugins/localization.d.ts +9 -0
  21. package/dist/plugins/localization.js +37 -0
  22. package/dist/plugins/media-gallery.d.ts +9 -0
  23. package/dist/plugins/media-gallery.js +57 -0
  24. package/dist/plugins/mobile-menu.d.ts +9 -0
  25. package/dist/plugins/mobile-menu.js +51 -0
  26. package/dist/plugins/offer-engine.d.ts +9 -0
  27. package/dist/plugins/offer-engine.js +57 -0
  28. package/dist/plugins/predictive-search.d.ts +9 -0
  29. package/dist/plugins/predictive-search.js +77 -0
  30. package/dist/plugins/promo-popup.d.ts +9 -0
  31. package/dist/plugins/promo-popup.js +117 -0
  32. package/dist/plugins/quantity-input.d.ts +9 -0
  33. package/dist/plugins/quantity-input.js +44 -0
  34. package/dist/plugins/quick-view.d.ts +9 -0
  35. package/dist/plugins/quick-view.js +69 -0
  36. package/dist/plugins/recently-viewed.d.ts +9 -0
  37. package/dist/plugins/recently-viewed.js +71 -0
  38. package/dist/plugins/reveal-on-scroll.d.ts +9 -0
  39. package/dist/plugins/reveal-on-scroll.js +37 -0
  40. package/dist/plugins/runtime-slot-loader.d.ts +9 -0
  41. package/dist/plugins/runtime-slot-loader.js +29 -0
  42. package/dist/plugins/seasonal-effects.d.ts +9 -0
  43. package/dist/plugins/seasonal-effects.js +17 -0
  44. package/dist/plugins/sticky-atc.d.ts +9 -0
  45. package/dist/plugins/sticky-atc.js +43 -0
  46. package/dist/plugins/tabs.d.ts +9 -0
  47. package/dist/plugins/tabs.js +50 -0
  48. package/dist/plugins/variant-selects.d.ts +9 -0
  49. package/dist/plugins/variant-selects.js +70 -0
  50. package/dist/popup-shell.css +91 -0
  51. package/dist/primitives.css +1430 -0
  52. package/dist/runtime-core.d.ts +51 -0
  53. package/dist/runtime-core.js +176 -0
  54. package/dist/section-gate.js +315 -86
  55. package/dist/sections.css +1116 -0
  56. package/dist/tokens.css +67 -0
  57. package/package.json +21 -1
@@ -0,0 +1,29 @@
1
+ // @gemboss/gem-framework/plugins/runtime-slot-loader: the gem-runtime plugin "runtime-slot-loader" as an ES module. Generated from
2
+ // packages/gem-framework/src/runtime.ts, the same lines gem-runtime.js carries; do not edit here.
3
+ import { mountPlugin } from "../runtime-core.js";
4
+
5
+ export const key = "runtime-slot-loader";
6
+ export const readyEvent = "gem:slot:ready";
7
+
8
+ function install({ document, window, target, mark, canListen, listen: __gemListen, registerPlugin, registerNoopPlugin }) {
9
+ registerPlugin('runtime-slot-loader', ({ api }) => {
10
+ const slots = document.querySelectorAll('[data-gem-runtime-slot], [data-gem-footer-block-builder], .gem-navigation-shell__layout');
11
+ let bound = 0;
12
+ slots.forEach((slot, index) => {
13
+ if (!mark(slot, 'runtime-slot-loader')) return;
14
+ if (slot.dataset) {
15
+ slot.dataset.gemRuntimeSlotState = 'ready';
16
+ if (!slot.dataset.gemRuntimeSlotIndex) slot.dataset.gemRuntimeSlotIndex = String(index);
17
+ }
18
+ bound += 1;
19
+ });
20
+ api.emit('gem:slot:ready', { source: 'gem-runtime', count: bound });
21
+ });
22
+ }
23
+
24
+ /** Bind every "runtime-slot-loader" hook inside root (default: the whole document). Returns unmount(). Mounting the same root twice binds once. */
25
+ export function mount(root, options) {
26
+ return mountPlugin(key, install, root, options);
27
+ }
28
+
29
+ export default mount;
@@ -0,0 +1,9 @@
1
+ // @gemboss/gem-framework/plugins/seasonal-effects: types of the ES module next to this file. Generated; do not edit here.
2
+ import type { MountOptions, Unmount } from "../runtime-core.js";
3
+
4
+ export type { MountOptions, Unmount };
5
+ export declare const key: "seasonal-effects";
6
+ export declare const readyEvent: "gem:seasonal:ready";
7
+ /** Bind every "seasonal-effects" hook inside root (default: the whole document). Returns unmount(). Mounting the same root twice binds once. */
8
+ export declare function mount(root?: ParentNode | null, options?: MountOptions): Unmount;
9
+ export default mount;
@@ -0,0 +1,17 @@
1
+ // @gemboss/gem-framework/plugins/seasonal-effects: the gem-runtime plugin "seasonal-effects" as an ES module. Generated from
2
+ // packages/gem-framework/src/runtime.ts, the same lines gem-runtime.js carries; do not edit here.
3
+ import { mountPlugin } from "../runtime-core.js";
4
+
5
+ export const key = "seasonal-effects";
6
+ export const readyEvent = "gem:seasonal:ready";
7
+
8
+ function install({ document, window, target, mark, canListen, listen: __gemListen, registerPlugin, registerNoopPlugin }) {
9
+ registerNoopPlugin("seasonal-effects", "gem:seasonal:ready");
10
+ }
11
+
12
+ /** Bind every "seasonal-effects" hook inside root (default: the whole document). Returns unmount(). Mounting the same root twice binds once. */
13
+ export function mount(root, options) {
14
+ return mountPlugin(key, install, root, options);
15
+ }
16
+
17
+ export default mount;
@@ -0,0 +1,9 @@
1
+ // @gemboss/gem-framework/plugins/sticky-atc: types of the ES module next to this file. Generated; do not edit here.
2
+ import type { MountOptions, Unmount } from "../runtime-core.js";
3
+
4
+ export type { MountOptions, Unmount };
5
+ export declare const key: "sticky-atc";
6
+ export declare const readyEvent: "gem:sticky-atc:ready";
7
+ /** Bind every "sticky-atc" hook inside root (default: the whole document). Returns unmount(). Mounting the same root twice binds once. */
8
+ export declare function mount(root?: ParentNode | null, options?: MountOptions): Unmount;
9
+ export default mount;
@@ -0,0 +1,43 @@
1
+ // @gemboss/gem-framework/plugins/sticky-atc: the gem-runtime plugin "sticky-atc" as an ES module. Generated from
2
+ // packages/gem-framework/src/runtime.ts, the same lines gem-runtime.js carries; do not edit here.
3
+ import { mountPlugin } from "../runtime-core.js";
4
+
5
+ export const key = "sticky-atc";
6
+ export const readyEvent = "gem:sticky-atc:ready";
7
+
8
+ function install({ document, window, target, mark, canListen, listen: __gemListen, registerPlugin, registerNoopPlugin }) {
9
+ registerPlugin('sticky-atc', ({ api }) => {
10
+ const bars = document.querySelectorAll('[data-gem-sticky-atc], .gem-sticky-atc');
11
+ let bound = 0;
12
+ const setState = (bar, state) => {
13
+ if (!bar || !bar.dataset) return;
14
+ if (bar.dataset.gemStickyAtcState === state) return;
15
+ bar.dataset.gemStickyAtcState = state;
16
+ api.emit(state === 'visible' ? 'gem:sticky-atc:show' : 'gem:sticky-atc:hide', { source: 'gem-runtime', id: bar.id || undefined });
17
+ };
18
+ bars.forEach((bar) => {
19
+ if (!mark(bar, 'sticky-atc')) return;
20
+ const cssThreshold = () => { try { return target.getComputedStyle ? Number(target.getComputedStyle(bar).getPropertyValue('--gem-sticky-atc-threshold')) : 0; } catch { return 0; } };
21
+ const threshold = bar.hasAttribute && bar.hasAttribute('data-gem-sticky-atc-threshold')
22
+ ? (Number(bar.getAttribute('data-gem-sticky-atc-threshold')) || cssThreshold() || 360)
23
+ : Number(bar.getAttribute && (bar.getAttribute('data-gem-sticky-threshold') || '240'));
24
+ const update = () => {
25
+ const scrollY = Number(target.scrollY || target.pageYOffset || 0);
26
+ setState(bar, scrollY >= threshold ? 'visible' : 'hidden');
27
+ };
28
+ update();
29
+ if (canListen(target)) __gemListen(target, 'scroll', update, { passive: true });
30
+ const form = bar.querySelector && bar.querySelector('form');
31
+ if (canListen(form)) __gemListen(form, 'submit', () => api.emit('gem:sticky-atc:submit', { source: 'gem-runtime', id: bar.id || undefined }));
32
+ bound += 1;
33
+ });
34
+ api.emit('gem:sticky-atc:ready', { source: 'gem-runtime', count: bound });
35
+ });
36
+ }
37
+
38
+ /** Bind every "sticky-atc" hook inside root (default: the whole document). Returns unmount(). Mounting the same root twice binds once. */
39
+ export function mount(root, options) {
40
+ return mountPlugin(key, install, root, options);
41
+ }
42
+
43
+ export default mount;
@@ -0,0 +1,9 @@
1
+ // @gemboss/gem-framework/plugins/tabs: types of the ES module next to this file. Generated; do not edit here.
2
+ import type { MountOptions, Unmount } from "../runtime-core.js";
3
+
4
+ export type { MountOptions, Unmount };
5
+ export declare const key: "tabs";
6
+ export declare const readyEvent: "gem:tabs:ready";
7
+ /** Bind every "tabs" hook inside root (default: the whole document). Returns unmount(). Mounting the same root twice binds once. */
8
+ export declare function mount(root?: ParentNode | null, options?: MountOptions): Unmount;
9
+ export default mount;
@@ -0,0 +1,50 @@
1
+ // @gemboss/gem-framework/plugins/tabs: the gem-runtime plugin "tabs" as an ES module. Generated from
2
+ // packages/gem-framework/src/runtime.ts, the same lines gem-runtime.js carries; do not edit here.
3
+ import { mountPlugin } from "../runtime-core.js";
4
+
5
+ export const key = "tabs";
6
+ export const readyEvent = "gem:tabs:ready";
7
+
8
+ function install({ document, window, target, mark, canListen, listen: __gemListen, registerPlugin, registerNoopPlugin }) {
9
+ registerPlugin('tabs', ({ api }) => {
10
+ const roots = document.querySelectorAll('[data-gem-tabs]');
11
+ let bound = 0;
12
+ roots.forEach((root) => {
13
+ if (!mark(root, 'tabs')) return;
14
+ const tabs = Array.prototype.slice.call(root.querySelectorAll('[data-gem-tab]'));
15
+ const panels = Array.prototype.slice.call(root.querySelectorAll('[data-gem-panel]'));
16
+ if (!tabs.length || !panels.length) return;
17
+ const select = (key, userInitiated) => {
18
+ tabs.forEach((t) => t.setAttribute('aria-selected', String(t.getAttribute('data-gem-tab') === key)));
19
+ let active = null;
20
+ panels.forEach((p) => {
21
+ if (p.getAttribute('data-gem-panel') === key) { p.removeAttribute('hidden'); active = p; }
22
+ else p.setAttribute('hidden', '');
23
+ });
24
+ if (userInitiated && active && active.getBoundingClientRect) {
25
+ const r = active.getBoundingClientRect();
26
+ const vh = window.innerHeight || document.documentElement.clientHeight;
27
+ if (!(r.top < vh * 0.85 && r.bottom > vh * 0.15) && active.scrollIntoView) {
28
+ active.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
29
+ }
30
+ }
31
+ api.emit('gem:tabs:change', { source: 'gem-runtime', key: key });
32
+ };
33
+ tabs.forEach((t) => {
34
+ if (!canListen(t)) return;
35
+ __gemListen(t, 'click', () => select(t.getAttribute('data-gem-tab'), true));
36
+ });
37
+ const initial = tabs.filter((t) => t.getAttribute('aria-selected') === 'true')[0] || tabs[0];
38
+ select(initial.getAttribute('data-gem-tab'), false);
39
+ bound += 1;
40
+ });
41
+ api.emit('gem:tabs:ready', { source: 'gem-runtime', count: bound });
42
+ });
43
+ }
44
+
45
+ /** Bind every "tabs" hook inside root (default: the whole document). Returns unmount(). Mounting the same root twice binds once. */
46
+ export function mount(root, options) {
47
+ return mountPlugin(key, install, root, options);
48
+ }
49
+
50
+ export default mount;
@@ -0,0 +1,9 @@
1
+ // @gemboss/gem-framework/plugins/variant-selects: types of the ES module next to this file. Generated; do not edit here.
2
+ import type { MountOptions, Unmount } from "../runtime-core.js";
3
+
4
+ export type { MountOptions, Unmount };
5
+ export declare const key: "variant-selects";
6
+ export declare const readyEvent: "gem:variant:ready";
7
+ /** Bind every "variant-selects" hook inside root (default: the whole document). Returns unmount(). Mounting the same root twice binds once. */
8
+ export declare function mount(root?: ParentNode | null, options?: MountOptions): Unmount;
9
+ export default mount;
@@ -0,0 +1,70 @@
1
+ // @gemboss/gem-framework/plugins/variant-selects: the gem-runtime plugin "variant-selects" as an ES module. Generated from
2
+ // packages/gem-framework/src/runtime.ts, the same lines gem-runtime.js carries; do not edit here.
3
+ import { mountPlugin } from "../runtime-core.js";
4
+
5
+ export const key = "variant-selects";
6
+ export const readyEvent = "gem:variant:ready";
7
+
8
+ function install({ document, window, target, mark, canListen, listen: __gemListen, registerPlugin, registerNoopPlugin }) {
9
+ registerPlugin('variant-selects', ({ api }) => {
10
+ const selects = document.querySelectorAll('[data-gem-variant-select], select[name="id"]');
11
+ let bound = 0;
12
+ selects.forEach((select) => {
13
+ if (!mark(select, 'variant-selects')) return;
14
+ let hasInitialized = false;
15
+ const update = () => {
16
+ const option = select.options && select.options[select.selectedIndex];
17
+ const available = !option || option.getAttribute('data-gem-variant-available') !== 'false';
18
+ const price = option && option.getAttribute('data-gem-variant-price');
19
+ const mediaId = option && option.getAttribute('data-gem-variant-media-id');
20
+ const form = select.closest && select.closest('form');
21
+ const scope = (form && form.closest && form.closest('[data-gem-section-id], .gem-section, [data-qa-surface]')) || (select.closest && select.closest('[data-gem-section-id], .gem-section, [data-qa-surface]')) || document;
22
+ const submit = form && form.querySelector && form.querySelector('[type="submit"]');
23
+ const status = form && form.querySelector && form.querySelector('[data-gem-variant-status]');
24
+ const priceOutput = scope && scope.querySelector && scope.querySelector('[data-gem-variant-price-output]');
25
+ const availabilityOutput = scope && scope.querySelector && scope.querySelector('[data-gem-variant-availability]');
26
+ if (form && form.dataset) form.dataset.gemSelectedVariantId = String(select.value || '');
27
+ if (form && form.dataset && price) form.dataset.gemSelectedVariantPrice = price;
28
+ if (form && form.dataset && mediaId) form.dataset.gemSelectedMediaId = mediaId;
29
+ if (submit) submit.disabled = !available;
30
+ if (submit) submit.setAttribute('aria-disabled', available ? 'false' : 'true');
31
+ if (status) status.textContent = available ? 'Selected variant available' : 'Selected variant unavailable';
32
+ if (hasInitialized && price && priceOutput) priceOutput.textContent = price;
33
+ if (availabilityOutput) {
34
+ availabilityOutput.textContent = available ? 'In stock' : 'Sold out';
35
+ availabilityOutput.classList && availabilityOutput.classList.toggle('gem-product-main__availability--in-stock', available);
36
+ availabilityOutput.classList && availabilityOutput.classList.toggle('gem-product-main__availability--sold-out', !available);
37
+ }
38
+ if (mediaId) {
39
+ const escapedMediaId = String(mediaId).replace(/["\\]/g, '\\$&');
40
+ const gallery = (scope && scope.querySelector && scope.querySelector('[data-gem-media-gallery], .gem-product-media-gallery')) || document.querySelector('[data-gem-media-gallery], .gem-product-media-gallery');
41
+ const thumb = gallery && gallery.querySelector && gallery.querySelector('[data-gem-media-id="' + escapedMediaId + '"]');
42
+ const mediaIndex = thumb && thumb.getAttribute && thumb.getAttribute('data-gem-media-index');
43
+ if (thumb && typeof thumb.click === 'function') thumb.click();
44
+ if (gallery && mediaIndex !== null && mediaIndex !== undefined) {
45
+ gallery.dataset && (gallery.dataset.gemMediaActiveIndex = String(mediaIndex));
46
+ gallery.querySelectorAll && gallery.querySelectorAll('[data-gem-media-thumb]').forEach((control) => {
47
+ const isActive = control.getAttribute && control.getAttribute('data-gem-media-index') === String(mediaIndex);
48
+ if (isActive) control.setAttribute('aria-current', 'true'); else control.removeAttribute('aria-current');
49
+ if (control.dataset) control.dataset.gemMediaActive = isActive ? 'true' : 'false';
50
+ });
51
+ }
52
+ }
53
+ api.emit('gem:variant:change', { source: 'gem-runtime', variantId: select.value || undefined, available, price, mediaId });
54
+ hasInitialized = true;
55
+ };
56
+ if (!canListen(select)) return;
57
+ __gemListen(select, 'change', update);
58
+ update();
59
+ bound += 1;
60
+ });
61
+ api.emit('gem:variant:ready', { source: 'gem-runtime', count: bound });
62
+ });
63
+ }
64
+
65
+ /** Bind every "variant-selects" hook inside root (default: the whole document). Returns unmount(). Mounting the same root twice binds once. */
66
+ export function mount(root, options) {
67
+ return mountPlugin(key, install, root, options);
68
+ }
69
+
70
+ export default mount;
@@ -0,0 +1,91 @@
1
+ .gem-popup-shell { padding: 0; }
2
+ .gem-popup-shell__dialog {
3
+ padding: 0; border: 0; margin: auto; color: var(--gem-color-text); background: var(--gem-color-background);
4
+ width: min(880px, 92vw); max-width: none; max-height: min(640px, 92vh); overflow: hidden;
5
+ border-radius: var(--gem-radius-lg); box-shadow: var(--gem-shadow-md);
6
+ }
7
+ .gem-popup-shell__dialog::backdrop { background: rgb(0 0 0 / 0.55); }
8
+ .gem-popup-shell__frame { position: relative; display: grid; grid-template-columns: 1fr 1fr; min-height: 520px; height: 100%; }
9
+ .gem-popup-shell__media { position: relative; min-width: 0; overflow: hidden; background: var(--gem-color-surface); }
10
+ .gem-popup-shell__image { display: block; width: 100%; height: 100%; object-fit: cover; }
11
+ .gem-popup-shell__panel {
12
+ position: relative; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: var(--gem-space-md);
13
+ padding: var(--gem-space-2xl) var(--gem-space-xl); overflow-y: auto; align-items: center; text-align: center;
14
+ }
15
+ .gem-popup-shell[data-gem-popup-align='start'] .gem-popup-shell__panel { align-items: stretch; text-align: start; }
16
+ .gem-popup-shell[data-gem-popup-desktop='split-right'] .gem-popup-shell__media { order: 2; }
17
+ .gem-popup-shell[data-gem-popup-media='none'] .gem-popup-shell__frame,
18
+ .gem-popup-shell[data-gem-popup-desktop='card'] .gem-popup-shell__frame { grid-template-columns: 1fr; }
19
+ @media (min-width: 750px) {
20
+ .gem-popup-shell[data-gem-popup-media='none'] .gem-popup-shell__dialog,
21
+ .gem-popup-shell[data-gem-popup-desktop='card'] .gem-popup-shell__dialog { width: min(480px, 92vw); }
22
+ }
23
+ .gem-popup-shell[data-gem-popup-media='none'] .gem-popup-shell__media { display: none; }
24
+ .gem-popup-shell[data-gem-popup-desktop='card'] .gem-popup-shell__media { max-height: 200px; }
25
+ .gem-popup-shell[data-gem-popup-desktop='card-over-image'] .gem-popup-shell__frame { grid-template-columns: 1fr; place-items: center; }
26
+ .gem-popup-shell[data-gem-popup-desktop='card-over-image'] .gem-popup-shell__media { position: absolute; inset: 0; }
27
+ .gem-popup-shell[data-gem-popup-desktop='card-over-image'] .gem-popup-shell__panel {
28
+ width: min(420px, 86%); margin: var(--gem-space-xl) 0; background: var(--gem-color-background); border-radius: var(--gem-radius-lg); box-shadow: var(--gem-shadow-sm);
29
+ }
30
+ .gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__media::after { content: ''; position: absolute; inset: 0; background: linear-gradient(rgb(0 0 0 / 0.35), rgb(0 0 0 / 0.6)); }
31
+ .gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__panel,
32
+ .gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__close { color: #fff; }
33
+ .gem-popup-shell__close {
34
+ position: absolute; inset-block-start: var(--gem-space-xs); inset-inline-end: var(--gem-space-xs); z-index: 2;
35
+ display: inline-grid; place-items: center; width: var(--gem-tap-min); height: var(--gem-tap-min); padding: 0;
36
+ border: 0; border-radius: var(--gem-radius-pill); color: inherit; background: transparent; cursor: pointer;
37
+ }
38
+ .gem-popup-shell__close:focus-visible { outline: var(--gem-focus-ring); outline-offset: var(--gem-focus-offset); }
39
+ .gem-popup-shell__teaser {
40
+ position: fixed; inset-block-end: var(--gem-space-md); inset-inline-end: var(--gem-space-md); z-index: 40;
41
+ min-height: var(--gem-tap-min); padding: 0 var(--gem-space-md); font: inherit; font-weight: 600; cursor: pointer;
42
+ color: var(--gem-color-accent-text); background: var(--gem-color-accent); border: 0; border-radius: var(--gem-radius-pill); box-shadow: var(--gem-shadow-md);
43
+ }
44
+ .gem-popup-shell__teaser[data-position='left'] { inset-inline-end: auto; inset-inline-start: var(--gem-space-md); }
45
+ .gem-popup-shell__teaser[hidden] { display: none; }
46
+ @media (min-width: 750px) {
47
+ .gem-popup-shell[data-gem-popup-desktop='fullscreen'] .gem-popup-shell__dialog { width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; box-shadow: none; }
48
+ .gem-popup-shell[data-gem-popup-desktop='fullscreen'] .gem-popup-shell__frame { min-height: 100%; }
49
+ .gem-popup-shell[data-gem-popup-desktop='fullscreen'] .gem-popup-shell__media { order: 2; }
50
+ .gem-popup-shell[data-gem-popup-desktop='fullscreen'] .gem-popup-shell__panel { padding: var(--gem-space-3xl); }
51
+ .gem-popup-shell[data-gem-popup-desktop='fullscreen'][data-gem-popup-align='start'] .gem-popup-shell__panel { padding-inline-start: max(var(--gem-space-3xl), 8vw); }
52
+ .gem-popup-shell[data-gem-popup-desktop='fullscreen'][data-gem-popup-media='background'] .gem-popup-shell__frame { grid-template-columns: 1fr; }
53
+ .gem-popup-shell[data-gem-popup-desktop='fullscreen'][data-gem-popup-media='background'][data-gem-popup-align='start'] .gem-popup-shell__frame { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
54
+ .gem-popup-shell[data-gem-popup-desktop='fullscreen'][data-gem-popup-media='background'] .gem-popup-shell__media { position: absolute; inset: 0; }
55
+ .gem-popup-shell[data-gem-popup-desktop='fullscreen'][data-gem-popup-media='background'] .gem-popup-shell__panel { position: relative; z-index: 1; }
56
+ .gem-popup-shell[data-gem-popup-desktop='card-over-image'][data-gem-popup-media='background'] .gem-popup-shell__panel { color: var(--gem-color-text); }
57
+ .gem-popup-shell[data-gem-popup-media='background']:is([data-gem-popup-desktop='split-left'], [data-gem-popup-desktop='split-right'], [data-gem-popup-desktop='card']) .gem-popup-shell__panel,
58
+ .gem-popup-shell[data-gem-popup-media='background']:is([data-gem-popup-desktop='split-left'], [data-gem-popup-desktop='split-right'], [data-gem-popup-desktop='card']) .gem-popup-shell__close { color: var(--gem-color-text); }
59
+ .gem-popup-shell[data-gem-popup-media='background']:is([data-gem-popup-desktop='split-left'], [data-gem-popup-desktop='split-right'], [data-gem-popup-desktop='card']) .gem-popup-shell__media::after { content: none; }
60
+ }
61
+ @media (max-width: 749px) {
62
+ .gem-popup-shell__dialog { width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; }
63
+ .gem-popup-shell[data-gem-popup-mobile='sheet'] .gem-popup-shell__dialog { height: auto; max-height: 88dvh; margin: auto 0 0; border-radius: var(--gem-radius-lg) var(--gem-radius-lg) 0 0; }
64
+ .gem-popup-shell__frame { grid-template-columns: 1fr; grid-template-rows: auto 1fr; min-height: 100%; }
65
+ .gem-popup-shell__panel { justify-content: flex-start; padding: var(--gem-space-3xl) var(--gem-space-lg) var(--gem-space-xl); }
66
+ .gem-popup-shell[data-gem-popup-media='none'] .gem-popup-shell__panel,
67
+ .gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__panel { justify-content: center; }
68
+ .gem-popup-shell[data-gem-popup-desktop='card-over-image'] .gem-popup-shell__panel { width: 100%; margin: 0; border-radius: 0; box-shadow: none; background: transparent; }
69
+ .gem-popup-shell[data-gem-popup-desktop='card-over-image'] .gem-popup-shell__media { position: relative; }
70
+ .gem-popup-shell__media { order: 2; max-height: 34dvh; }
71
+ .gem-popup-shell[data-gem-popup-media='top'] .gem-popup-shell__media { order: 0; }
72
+ .gem-popup-shell[data-gem-popup-media='top'] .gem-popup-shell__panel { padding-top: var(--gem-space-lg); }
73
+ .gem-popup-shell[data-gem-popup-media='none'] .gem-popup-shell__frame,
74
+ .gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__frame { grid-template-rows: 1fr; }
75
+ .gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__media { position: absolute; inset: 0; max-height: none; }
76
+ }
77
+ :root:not(:has([data-gem-canvas])) .gem-popup-shell[data-gem-popup-preview='true'] { position: fixed; inset: 0; z-index: 1000; padding: 0; background: rgb(0 0 0 / 0.55); }
78
+ :root:not(:has([data-gem-canvas])) .gem-popup-shell[data-gem-popup-preview='true'] .gem-popup-shell__dialog { position: fixed; inset: 0; display: block; }
79
+ :root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'] .gem-popup-shell__dialog { position: relative; display: block; inset: auto; }
80
+ :root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'] { padding: var(--gem-space-xl) var(--gem-layout-gutter); background: rgb(0 0 0 / 0.55); }
81
+ @media (min-width: 750px) {
82
+ :root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'][data-gem-popup-desktop='fullscreen'] { padding: 0; }
83
+ :root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'][data-gem-popup-desktop='fullscreen'] .gem-popup-shell__dialog { height: 720px; max-height: none; }
84
+ }
85
+ @media (max-width: 749px) {
86
+ :root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'] { padding: 0; }
87
+ :root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'] .gem-popup-shell__dialog { height: 844px; max-height: none; width: 100%; max-width: 100%; }
88
+ :root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'][data-gem-popup-mobile='sheet'] { padding-top: 160px; }
89
+ :root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'][data-gem-popup-mobile='sheet'] .gem-popup-shell__dialog { min-height: 0; }
90
+ }
91
+