rebly-sections 1.3.0 → 1.4.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.
@@ -1,32 +1,66 @@
1
- {%- comment -%} rebly-sections: Image Gallery | Category: media | OS2.0 {%- endcomment -%}
1
+ {%- comment -%} rebly-sections: Image Gallery | Category: media | OS2.0 | Masonry + scroll-reveal {%- endcomment -%}
2
+ {%- assign font = section.settings.heading_font -%}
3
+ {%- assign heading_tag = section.settings.heading_tag -%}
2
4
 
3
- <section id="section-{{ section.id }}" class="image-gallery">
4
- <div class="image-gallery__container">
5
+ {{ font | font_face: font_display: 'swap' }}
6
+
7
+ <section id="section-{{ section.id }}" class="image-gallery color-{{ section.settings.color_scheme }}">
8
+ <div class="image-gallery__container" style="
9
+ --pt: {{ section.settings.padding_top }}px;
10
+ --pb: {{ section.settings.padding_bottom }}px;
11
+ --heading-size: {{ section.settings.heading_font_size }}px;
12
+ --heading-font: {{ font.family }}, {{ font.fallback_families }};
13
+ --heading-weight: {{ font.weight }};
14
+ ">
5
15
 
6
16
  {%- if section.settings.heading != blank -%}
7
- <h2 class="image-gallery__heading">{{ section.settings.heading | escape }}</h2>
17
+ <{{ heading_tag }} class="image-gallery__heading">{{ section.settings.heading | escape }}</{{ heading_tag }}>
8
18
  {%- endif -%}
9
19
 
10
- <div class="image-gallery__grid" style="--cols: {{ section.settings.columns }};">
20
+ <div class="image-gallery__grid">
11
21
  {%- for block in section.blocks -%}
12
22
  {%- if block.type == 'gallery-item' -%}
13
- <div class="image-gallery__item" {{ block.shopify_attributes }}>
23
+ {%- comment -%} Alternate tall rows for masonry rhythm: every 3rd item is taller {%- endcomment -%}
24
+ {%- assign is_tall = forloop.index | modulo: 3 -%}
25
+ <div
26
+ class="image-gallery__item{% if is_tall == 0 %} image-gallery__item--tall{% endif %} gallery-reveal"
27
+ {{ block.shopify_attributes }}
28
+ >
14
29
  {%- if block.settings.image != blank -%}
15
- {%- if section.settings.enable_lightbox -%}
16
- <a
17
- href="{{ block.settings.image | image_url: width: 1600 }}"
18
- class="image-gallery__link"
19
- data-lightbox="gallery-{{ section.id }}"
20
- data-title="{{ block.settings.caption | escape }}"
30
+ {%- comment -%} Lightbox via :target — pure CSS, zero JS {%- endcomment -%}
31
+ <a href="#gallery-{{ section.id }}-{{ forloop.index }}" class="image-gallery__zoom-trigger" aria-label="Open image">
32
+ <img
33
+ src="{{ block.settings.image | image_url: width: 800 }}"
34
+ srcset="
35
+ {{ block.settings.image | image_url: width: 400 }} 400w,
36
+ {{ block.settings.image | image_url: width: 800 }} 800w,
37
+ {{ block.settings.image | image_url: width: 1200 }} 1200w"
38
+ sizes="(max-width: 749px) 100vw, (max-width: 989px) 50vw, 33vw"
39
+ loading="lazy"
40
+ alt="{{ block.settings.caption | default: block.settings.image.alt | escape }}"
41
+ class="image-gallery__img"
42
+ width="{{ block.settings.image.width }}"
43
+ height="{{ block.settings.image.height }}"
44
+ >
45
+ <div class="image-gallery__hover-overlay" aria-hidden="true">
46
+ <span class="image-gallery__zoom-icon">&#x2B2C;</span>
47
+ </div>
48
+ </a>
49
+ {%- comment -%} Lightbox overlay — triggered by :target selector {%- endcomment -%}
50
+ <div id="gallery-{{ section.id }}-{{ forloop.index }}" class="image-gallery__lightbox" role="dialog">
51
+ <a href="#" class="image-gallery__lightbox-close" aria-label="Close">&times;</a>
52
+ <img
53
+ src="{{ block.settings.image | image_url: width: 1600 }}"
54
+ loading="lazy"
55
+ alt="{{ block.settings.caption | default: block.settings.image.alt | escape }}"
56
+ class="image-gallery__lightbox-img"
21
57
  >
22
- {%- endif -%}
23
- {{- block.settings.image | image_url: width: 600 | image_tag: loading: 'lazy', alt: block.settings.caption, class: 'image-gallery__img' -}}
24
- {%- if section.settings.enable_lightbox -%}</a>{%- endif -%}
25
- {%- if block.settings.caption != blank -%}
26
- <p class="image-gallery__caption">{{ block.settings.caption | escape }}</p>
27
- {%- endif -%}
58
+ {%- if block.settings.caption != blank -%}
59
+ <p class="image-gallery__lightbox-caption">{{ block.settings.caption | escape }}</p>
60
+ {%- endif -%}
61
+ </div>
28
62
  {%- else -%}
29
- {{ 'image' | placeholder_svg_tag: 'image-gallery__img' }}
63
+ {{ 'image' | placeholder_svg_tag: 'image-gallery__placeholder' }}
30
64
  {%- endif -%}
31
65
  </div>
32
66
  {%- endif -%}
@@ -37,26 +71,117 @@
37
71
  </section>
38
72
 
39
73
  <style>
40
- #section-{{ section.id }} .image-gallery__container { max-width: 1200px; margin: 0 auto; padding: 4rem 2rem; }
41
- #section-{{ section.id }} .image-gallery__heading { font-size: 2rem; text-align: center; margin: 0 0 2rem; color: inherit; }
42
- #section-{{ section.id }} .image-gallery__grid { display: grid; grid-template-columns: repeat(var(--cols, 3), 1fr); gap: 1rem; }
43
- #section-{{ section.id }} .image-gallery__item { position: relative; overflow: hidden; border-radius: 4px; }
44
- #section-{{ section.id }} .image-gallery__img { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; transition: transform 0.3s; }
45
- #section-{{ section.id }} .image-gallery__item:hover .image-gallery__img { transform: scale(1.04); }
46
- #section-{{ section.id }} .image-gallery__link { display: block; overflow: hidden; }
47
- #section-{{ section.id }} .image-gallery__caption { font-size: 0.85rem; opacity: 0.7; padding: 0.4rem 0; text-align: center; color: inherit; }
48
- @media (max-width: 749px) { #section-{{ section.id }} .image-gallery__grid { grid-template-columns: repeat(2, 1fr); } }
74
+ /* ── Layout ── */
75
+ #section-{{ section.id }} .image-gallery__container {
76
+ max-width: 1280px; margin: 0 auto;
77
+ padding: var(--pt, 64px) 2rem var(--pb, 64px);
78
+ }
79
+ #section-{{ section.id }} .image-gallery__heading {
80
+ font-family: var(--heading-font); font-weight: var(--heading-weight);
81
+ font-size: clamp(1.75rem, 3vw, var(--heading-size, 2.5rem));
82
+ text-align: center; margin: 0 0 2.5rem; color: rgb(var(--color-foreground));
83
+ }
84
+ /* ── CSS Grid masonry via grid-auto-rows ── */
85
+ #section-{{ section.id }} .image-gallery__grid {
86
+ display: grid;
87
+ grid-template-columns: repeat(3, 1fr);
88
+ grid-auto-rows: 260px;
89
+ gap: 0.875rem;
90
+ }
91
+ #section-{{ section.id }} .image-gallery__item { position: relative; overflow: hidden; border-radius: 6px; }
92
+ #section-{{ section.id }} .image-gallery__item--tall { grid-row: span 2; }
93
+ /* ── Image zoom on hover — GPU transform only ── */
94
+ #section-{{ section.id }} .image-gallery__img {
95
+ width: 100%; height: 100%; object-fit: cover; display: block;
96
+ transition: transform 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94);
97
+ will-change: transform;
98
+ }
99
+ #section-{{ section.id }} .image-gallery__item:hover .image-gallery__img { transform: scale(1.06); }
100
+ /* ── Hover overlay ── */
101
+ #section-{{ section.id }} .image-gallery__zoom-trigger { display: block; height: 100%; }
102
+ #section-{{ section.id }} .image-gallery__hover-overlay {
103
+ position: absolute; inset: 0; display: grid; place-items: center;
104
+ background: rgba(0,0,0,0.35); opacity: 0;
105
+ transition: opacity 0.3s ease;
106
+ }
107
+ #section-{{ section.id }} .image-gallery__item:hover .image-gallery__hover-overlay { opacity: 1; }
108
+ #section-{{ section.id }} .image-gallery__zoom-icon { font-size: 2rem; color: #fff; line-height: 1; }
109
+ /* ── CSS-only lightbox via :target ── */
110
+ #section-{{ section.id }} .image-gallery__lightbox {
111
+ position: fixed; inset: 0; z-index: 9999; display: none;
112
+ background: rgba(0,0,0,0.92); place-items: center;
113
+ flex-direction: column; gap: 1rem; padding: 2rem;
114
+ }
115
+ #section-{{ section.id }} .image-gallery__lightbox:target { display: flex; }
116
+ #section-{{ section.id }} .image-gallery__lightbox-close {
117
+ position: absolute; top: 1rem; right: 1.5rem; color: #fff;
118
+ font-size: 2.5rem; text-decoration: none; line-height: 1;
119
+ }
120
+ #section-{{ section.id }} .image-gallery__lightbox-img {
121
+ max-width: 90vw; max-height: 85vh; object-fit: contain; border-radius: 4px;
122
+ }
123
+ #section-{{ section.id }} .image-gallery__lightbox-caption { color: rgba(255,255,255,0.8); font-size: 0.9rem; }
124
+ #section-{{ section.id }} .image-gallery__placeholder { width: 100%; height: 100%; }
125
+ /* ── Scroll-reveal — starts hidden, JS adds .is-visible ── */
126
+ #section-{{ section.id }} .gallery-reveal {
127
+ opacity: 0; transform: translateY(32px);
128
+ transition: opacity 0.6s ease, transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
129
+ }
130
+ #section-{{ section.id }} .gallery-reveal.is-visible { opacity: 1; transform: translateY(0); }
131
+ /* ── Reduced motion ── */
132
+ @media (prefers-reduced-motion: reduce) {
133
+ #section-{{ section.id }} .gallery-reveal { opacity: 1; transform: none; transition: none; }
134
+ #section-{{ section.id }} .image-gallery__img { transition: none; }
135
+ #section-{{ section.id }} .image-gallery__hover-overlay { transition: none; }
136
+ }
137
+ /* ── Responsive breakpoints ── */
138
+ @media (max-width: 989px) {
139
+ #section-{{ section.id }} .image-gallery__grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 220px; }
140
+ }
141
+ @media (max-width: 749px) {
142
+ #section-{{ section.id }} .image-gallery__grid { grid-template-columns: 1fr; grid-auto-rows: 240px; }
143
+ #section-{{ section.id }} .image-gallery__item--tall { grid-row: span 1; }
144
+ }
49
145
  </style>
50
146
 
147
+ <script>
148
+ /* Stagger scroll-reveal via Intersection Observer */
149
+ (function() {
150
+ var items = document.querySelectorAll('#section-{{ section.id }} .gallery-reveal');
151
+ if (!items.length) return;
152
+ if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
153
+ items.forEach(function(el) { el.classList.add('is-visible'); });
154
+ return;
155
+ }
156
+ var observer = new IntersectionObserver(function(entries) {
157
+ entries.forEach(function(entry, i) {
158
+ if (entry.isIntersecting) {
159
+ /* Stagger each item by 80ms */
160
+ setTimeout(function() { entry.target.classList.add('is-visible'); }, i * 80);
161
+ observer.unobserve(entry.target);
162
+ }
163
+ });
164
+ }, { threshold: 0.12 });
165
+ items.forEach(function(el) { observer.observe(el); });
166
+ })();
167
+ </script>
168
+
51
169
  {% schema %}
52
170
  {
53
171
  "name": "Image Gallery",
54
172
  "tag": "section",
55
173
  "class": "section-image-gallery",
56
174
  "settings": [
57
- { "type": "text", "id": "heading", "label": "Heading" },
58
- { "type": "range", "id": "columns", "label": "Columns", "min": 2, "max": 5, "step": 1, "default": 3 },
59
- { "type": "checkbox", "id": "enable_lightbox", "label": "Enable Lightbox Links", "default": false }
175
+ { "type": "color_scheme", "id": "color_scheme", "label": "Color Scheme", "default": "scheme-1" },
176
+ { "type": "font_picker", "id": "heading_font", "label": "Heading Font", "default": "helvetica_n4" },
177
+ { "type": "range", "id": "heading_font_size", "label": "Heading Size (px)", "min": 20, "max": 56, "step": 2, "default": 40 },
178
+ { "type": "select", "id": "heading_tag", "label": "Heading Tag", "options": [
179
+ { "value": "h1", "label": "H1" }, { "value": "h2", "label": "H2" },
180
+ { "value": "h3", "label": "H3" }, { "value": "h4", "label": "H4" }
181
+ ], "default": "h2" },
182
+ { "type": "text", "id": "heading", "label": "Heading", "default": "Our Gallery" },
183
+ { "type": "range", "id": "padding_top", "label": "Padding Top (px)", "min": 0, "max": 120, "step": 8, "default": 64 },
184
+ { "type": "range", "id": "padding_bottom", "label": "Padding Bottom (px)", "min": 0, "max": 120, "step": 8, "default": 64 }
60
185
  ],
61
186
  "blocks": [
62
187
  {
@@ -71,7 +196,10 @@
71
196
  ],
72
197
  "presets": [{
73
198
  "name": "Image Gallery",
74
- "blocks": [{ "type": "gallery-item" }, { "type": "gallery-item" }, { "type": "gallery-item" }, { "type": "gallery-item" }, { "type": "gallery-item" }, { "type": "gallery-item" }]
199
+ "blocks": [
200
+ { "type": "gallery-item" }, { "type": "gallery-item" }, { "type": "gallery-item" },
201
+ { "type": "gallery-item" }, { "type": "gallery-item" }, { "type": "gallery-item" }
202
+ ]
75
203
  }]
76
204
  }
77
205
  {% endschema %}
@@ -1,44 +1,90 @@
1
- {%- comment -%} rebly-sections: Pricing Table | Category: conversion | OS2.0 {%- endcomment -%}
1
+ {%- comment -%} rebly-sections: Pricing Table | Category: conversion | OS2.0 | Toggle + animations {%- endcomment -%}
2
+ {%- assign font = section.settings.heading_font -%}
3
+ {%- assign heading_tag = section.settings.heading_tag -%}
2
4
 
3
- <section id="section-{{ section.id }}" class="pricing-table">
4
- <div class="pricing-table__container">
5
+ {{ font | font_face: font_display: 'swap' }}
5
6
 
6
- {%- if section.settings.heading != blank or section.settings.subheading != blank -%}
7
- <div class="pricing-table__header">
8
- {%- if section.settings.heading != blank -%}
9
- <h2 class="pricing-table__heading">{{ section.settings.heading | escape }}</h2>
10
- {%- endif -%}
11
- {%- if section.settings.subheading != blank -%}
12
- <p class="pricing-table__subheading">{{ section.settings.subheading | escape }}</p>
13
- {%- endif -%}
14
- </div>
15
- {%- endif -%}
7
+ <section id="section-{{ section.id }}" class="pricing-table color-{{ section.settings.color_scheme }}">
8
+ <div class="pricing-table__container" style="
9
+ --pt: {{ section.settings.padding_top }}px;
10
+ --pb: {{ section.settings.padding_bottom }}px;
11
+ --heading-size: {{ section.settings.heading_font_size }}px;
12
+ --heading-font: {{ font.family }}, {{ font.fallback_families }};
13
+ --heading-weight: {{ font.weight }};
14
+ ">
15
+
16
+ <div class="pricing-table__header">
17
+ {%- if section.settings.heading != blank -%}
18
+ <{{ heading_tag }} class="pricing-table__heading">{{ section.settings.heading | escape }}</{{ heading_tag }}>
19
+ {%- endif -%}
20
+ {%- if section.settings.subheading != blank -%}
21
+ <p class="pricing-table__subheading">{{ section.settings.subheading | escape }}</p>
22
+ {%- endif -%}
23
+
24
+ {%- comment -%} CSS-only monthly/annual toggle via checkbox + label {%- endcomment -%}
25
+ {%- if section.settings.show_toggle -%}
26
+ <div class="pricing-table__toggle-wrap">
27
+ <span class="pricing-table__toggle-label{% unless section.settings.default_annual %} is-active{% endunless %}">
28
+ {{ section.settings.label_monthly | default: 'Monthly' }}
29
+ </span>
30
+ <input type="checkbox" id="pt-toggle-{{ section.id }}" class="pricing-table__toggle-input"
31
+ {% if section.settings.default_annual %}checked{% endif %}>
32
+ <label for="pt-toggle-{{ section.id }}" class="pricing-table__toggle-pill" aria-label="Toggle billing period"></label>
33
+ <span class="pricing-table__toggle-label{% if section.settings.default_annual %} is-active{% endif %}">
34
+ {{ section.settings.label_annual | default: 'Annual' }}
35
+ <em class="pricing-table__toggle-badge">{{ section.settings.annual_badge | default: 'Save 20%' }}</em>
36
+ </span>
37
+ </div>
38
+ {%- endif -%}
39
+ </div>
16
40
 
17
41
  <div class="pricing-table__tiers">
18
42
  {%- for block in section.blocks -%}
19
43
  {%- if block.type == 'pricing-tier' -%}
20
- <div class="pricing-table__tier{% if block.settings.highlighted %} pricing-table__tier--featured{% endif %}" {{ block.shopify_attributes }}>
44
+ <div class="pricing-table__tier pricing-reveal{% if block.settings.highlighted %} pricing-table__tier--featured{% endif %}"
45
+ {{ block.shopify_attributes }}>
46
+
47
+ {%- if block.settings.highlighted and section.settings.popular_badge != blank -%}
48
+ <div class="pricing-table__badge">{{ section.settings.popular_badge | escape }}</div>
49
+ {%- endif -%}
50
+
21
51
  {%- if block.settings.plan_name != blank -%}
22
52
  <h3 class="pricing-table__plan-name">{{ block.settings.plan_name | escape }}</h3>
23
53
  {%- endif -%}
54
+
55
+ {%- comment -%} Monthly / annual price swap controlled by CSS sibling selector on checkbox {%- endcomment -%}
24
56
  <div class="pricing-table__price-wrap">
25
- <span class="pricing-table__price">{{ block.settings.price | escape }}</span>
57
+ <span class="pricing-table__price pricing-table__price--monthly">
58
+ {{ block.settings.price_monthly | default: block.settings.price | escape }}
59
+ </span>
60
+ <span class="pricing-table__price pricing-table__price--annual">
61
+ {{ block.settings.price_annual | default: block.settings.price | escape }}
62
+ </span>
26
63
  {%- if block.settings.period != blank -%}
27
64
  <span class="pricing-table__period">/ {{ block.settings.period | escape }}</span>
28
65
  {%- endif -%}
29
66
  </div>
67
+
68
+ {%- if block.settings.description != blank -%}
69
+ <p class="pricing-table__desc">{{ block.settings.description | escape }}</p>
70
+ {%- endif -%}
71
+
30
72
  {%- if block.settings.features != blank -%}
31
73
  <ul class="pricing-table__features">
32
74
  {%- assign feature_list = block.settings.features | split: "\n" -%}
33
75
  {%- for feature in feature_list -%}
34
76
  {%- if feature != blank -%}
35
- <li>{{ feature | escape }}</li>
77
+ <li class="pricing-table__feature-item">
78
+ <span class="pricing-table__check" aria-hidden="true">&#10003;</span>
79
+ {{ feature | escape }}
80
+ </li>
36
81
  {%- endif -%}
37
82
  {%- endfor -%}
38
83
  </ul>
39
84
  {%- endif -%}
85
+
40
86
  {%- if block.settings.button_label != blank -%}
41
- <a href="{{ block.settings.button_link }}" class="pricing-table__btn">
87
+ <a href="{{ block.settings.button_link }}" class="pricing-table__btn{% if block.settings.highlighted %} pricing-table__btn--featured{% endif %}">
42
88
  {{ block.settings.button_label | escape }}
43
89
  </a>
44
90
  {%- endif -%}
@@ -51,44 +97,186 @@
51
97
  </section>
52
98
 
53
99
  <style>
54
- #section-{{ section.id }} .pricing-table__container { max-width: 1100px; margin: 0 auto; padding: 4rem 2rem; }
100
+ /* ── Layout ── */
101
+ #section-{{ section.id }} .pricing-table__container {
102
+ max-width: 1100px; margin: 0 auto;
103
+ padding: var(--pt, 80px) 2rem var(--pb, 80px);
104
+ }
55
105
  #section-{{ section.id }} .pricing-table__header { text-align: center; margin-bottom: 3rem; }
56
- #section-{{ section.id }} .pricing-table__heading { font-size: 2rem; margin: 0 0 0.75rem; color: inherit; }
57
- #section-{{ section.id }} .pricing-table__subheading { opacity: 0.7; margin: 0; color: inherit; }
58
- #section-{{ section.id }} .pricing-table__tiers { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; align-items: start; }
59
- #section-{{ section.id }} .pricing-table__tier { border: 1px solid rgba(0,0,0,0.12); border-radius: 8px; padding: 2rem; }
60
- #section-{{ section.id }} .pricing-table__tier--featured { border-color: #000; border-width: 2px; box-shadow: 0 4px 20px rgba(0,0,0,0.12); }
61
- #section-{{ section.id }} .pricing-table__plan-name { font-size: 1.25rem; margin: 0 0 1rem; text-transform: uppercase; letter-spacing: 0.05em; color: inherit; }
62
- #section-{{ section.id }} .pricing-table__price-wrap { margin-bottom: 1.5rem; }
63
- #section-{{ section.id }} .pricing-table__price { font-size: 2.5rem; font-weight: 700; color: inherit; }
64
- #section-{{ section.id }} .pricing-table__period { opacity: 0.6; color: inherit; }
106
+ #section-{{ section.id }} .pricing-table__heading {
107
+ font-family: var(--heading-font); font-weight: var(--heading-weight);
108
+ font-size: clamp(1.75rem, 3vw, var(--heading-size, 2.5rem));
109
+ margin: 0 0 0.75rem; color: rgb(var(--color-foreground));
110
+ }
111
+ #section-{{ section.id }} .pricing-table__subheading {
112
+ opacity: 0.7; margin: 0 0 1.5rem; color: rgb(var(--color-foreground));
113
+ }
114
+ /* ── CSS-only toggle ── */
115
+ #section-{{ section.id }} .pricing-table__toggle-input { display: none; }
116
+ #section-{{ section.id }} .pricing-table__toggle-wrap {
117
+ display: inline-flex; align-items: center; gap: 0.75rem; margin-top: 0.5rem;
118
+ }
119
+ #section-{{ section.id }} .pricing-table__toggle-label { font-size: 0.9rem; opacity: 0.65; }
120
+ #section-{{ section.id }} .pricing-table__toggle-label.is-active { opacity: 1; font-weight: 600; }
121
+ #section-{{ section.id }} .pricing-table__toggle-pill {
122
+ display: inline-block; width: 48px; height: 26px; border-radius: 13px;
123
+ background: rgb(var(--color-button)); cursor: pointer; position: relative;
124
+ transition: background 0.3s;
125
+ }
126
+ #section-{{ section.id }} .pricing-table__toggle-pill::after {
127
+ content: ''; position: absolute; top: 3px; left: 3px;
128
+ width: 20px; height: 20px; border-radius: 50%; background: #fff;
129
+ transition: transform 0.3s cubic-bezier(0.22,1,0.36,1);
130
+ }
131
+ #section-{{ section.id }} .pricing-table__toggle-input:checked ~ .pricing-table__tiers .pricing-table__toggle-pill::after { transform: translateX(22px); }
132
+ /* Price visibility controlled by checkbox state via general sibling */
133
+ #section-{{ section.id }} .pricing-table__price--annual { display: none; }
134
+ #section-{{ section.id }} .pricing-table__toggle-input:checked ~ .pricing-table__tiers .pricing-table__price--monthly { display: none; }
135
+ #section-{{ section.id }} .pricing-table__toggle-input:checked ~ .pricing-table__tiers .pricing-table__price--annual { display: inline; }
136
+ #section-{{ section.id }} .pricing-table__toggle-badge {
137
+ display: inline-block; font-size: 0.7rem; font-style: normal; font-weight: 600;
138
+ background: rgb(var(--color-button)); color: rgb(var(--color-button-text));
139
+ padding: 0.15em 0.5em; border-radius: 20px; margin-left: 0.35rem; vertical-align: middle;
140
+ }
141
+ /* ── Cards ── */
142
+ #section-{{ section.id }} .pricing-table__tiers {
143
+ display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
144
+ gap: 1.5rem; align-items: start;
145
+ }
146
+ #section-{{ section.id }} .pricing-table__tier {
147
+ border: 1px solid rgba(var(--color-foreground), 0.12); border-radius: 12px;
148
+ padding: 2rem; position: relative; background: rgb(var(--color-background));
149
+ transition: transform 0.3s cubic-bezier(0.22,1,0.36,1), box-shadow 0.3s ease;
150
+ will-change: transform;
151
+ }
152
+ #section-{{ section.id }} .pricing-table__tier:hover {
153
+ transform: translateY(-6px);
154
+ box-shadow: 0 16px 48px rgba(var(--color-foreground), 0.12);
155
+ }
156
+ /* ── Featured card with pulse-glow ── */
157
+ #section-{{ section.id }} .pricing-table__tier--featured {
158
+ border-color: rgb(var(--color-button)); border-width: 2px;
159
+ box-shadow: 0 8px 32px rgba(var(--color-button), 0.2);
160
+ animation: pricingGlow 3s ease-in-out infinite;
161
+ }
162
+ @keyframes pricingGlow {
163
+ 0%, 100% { box-shadow: 0 8px 32px rgba(var(--color-button), 0.2); }
164
+ 50% { box-shadow: 0 8px 48px rgba(var(--color-button), 0.45); }
165
+ }
166
+ #section-{{ section.id }} .pricing-table__badge {
167
+ position: absolute; top: -0.75rem; left: 50%; transform: translateX(-50%);
168
+ background: rgb(var(--color-button)); color: rgb(var(--color-button-text));
169
+ font-size: 0.75rem; font-weight: 700; padding: 0.25em 1em; border-radius: 20px;
170
+ white-space: nowrap; letter-spacing: 0.05em;
171
+ }
172
+ #section-{{ section.id }} .pricing-table__plan-name {
173
+ font-size: 0.875rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
174
+ color: rgb(var(--color-foreground)); margin: 0 0 1rem; opacity: 0.65;
175
+ }
176
+ #section-{{ section.id }} .pricing-table__price-wrap { margin-bottom: 0.5rem; }
177
+ #section-{{ section.id }} .pricing-table__price {
178
+ font-size: 3rem; font-weight: 800; line-height: 1; color: rgb(var(--color-foreground));
179
+ }
180
+ #section-{{ section.id }} .pricing-table__period { opacity: 0.55; color: rgb(var(--color-foreground)); font-size: 0.9rem; }
181
+ #section-{{ section.id }} .pricing-table__desc { font-size: 0.9rem; opacity: 0.65; margin: 0.5rem 0 1.25rem; color: rgb(var(--color-foreground)); }
65
182
  #section-{{ section.id }} .pricing-table__features { list-style: none; margin: 0 0 2rem; padding: 0; }
66
- #section-{{ section.id }} .pricing-table__features li { padding: 0.4rem 0; border-bottom: 1px solid rgba(0,0,0,0.07); font-size: 0.95rem; color: inherit; }
67
- #section-{{ section.id }} .pricing-table__btn { display: block; text-align: center; padding: 0.85rem 1.5rem; background: #000; color: #fff; text-decoration: none; border-radius: 4px; font-weight: 600; }
68
- #section-{{ section.id }} .pricing-table__tier--featured .pricing-table__btn { background: #000; }
183
+ #section-{{ section.id }} .pricing-table__feature-item {
184
+ display: flex; align-items: flex-start; gap: 0.5rem;
185
+ padding: 0.45rem 0; border-bottom: 1px solid rgba(var(--color-foreground), 0.07);
186
+ font-size: 0.9375rem; color: rgb(var(--color-foreground));
187
+ }
188
+ #section-{{ section.id }} .pricing-table__check { color: rgb(var(--color-button)); flex-shrink: 0; }
189
+ #section-{{ section.id }} .pricing-table__btn {
190
+ display: block; text-align: center; padding: 0.875rem 1.5rem; border-radius: 6px;
191
+ font-weight: 600; text-decoration: none; font-size: 0.9375rem;
192
+ border: 2px solid rgb(var(--color-foreground)); color: rgb(var(--color-foreground));
193
+ transition: transform 0.2s ease, background 0.2s ease, color 0.2s ease;
194
+ }
195
+ #section-{{ section.id }} .pricing-table__btn:hover { transform: translateY(-2px); background: rgb(var(--color-foreground)); color: rgb(var(--color-background)); }
196
+ #section-{{ section.id }} .pricing-table__btn--featured {
197
+ background: rgb(var(--color-button)); color: rgb(var(--color-button-text)); border-color: transparent;
198
+ }
199
+ #section-{{ section.id }} .pricing-table__btn--featured:hover { background: rgb(var(--color-button)); opacity: 0.88; }
200
+ /* ── Scroll-reveal ── */
201
+ #section-{{ section.id }} .pricing-reveal {
202
+ opacity: 0; transform: translateY(28px);
203
+ transition: opacity 0.55s ease, transform 0.55s cubic-bezier(0.22,1,0.36,1);
204
+ }
205
+ #section-{{ section.id }} .pricing-reveal.is-visible { opacity: 1; transform: translateY(0); }
206
+ /* ── Reduced motion ── */
207
+ @media (prefers-reduced-motion: reduce) {
208
+ #section-{{ section.id }} .pricing-reveal { opacity: 1; transform: none; transition: none; }
209
+ #section-{{ section.id }} .pricing-table__tier { transition: none; }
210
+ #section-{{ section.id }} .pricing-table__tier--featured { animation: none; }
211
+ }
212
+ /* ── Responsive ── */
213
+ @media (max-width: 749px) {
214
+ #section-{{ section.id }} .pricing-table__tiers { grid-template-columns: 1fr; }
215
+ }
216
+ @media (min-width: 750px) and (max-width: 989px) {
217
+ #section-{{ section.id }} .pricing-table__tiers { grid-template-columns: repeat(2, 1fr); }
218
+ }
69
219
  </style>
70
220
 
221
+ <script>
222
+ /* Stagger entrance on scroll */
223
+ (function() {
224
+ var items = document.querySelectorAll('#section-{{ section.id }} .pricing-reveal');
225
+ if (!items.length) return;
226
+ if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
227
+ items.forEach(function(el) { el.classList.add('is-visible'); });
228
+ return;
229
+ }
230
+ var observer = new IntersectionObserver(function(entries) {
231
+ entries.forEach(function(entry, i) {
232
+ if (entry.isIntersecting) {
233
+ setTimeout(function() { entry.target.classList.add('is-visible'); }, i * 100);
234
+ observer.unobserve(entry.target);
235
+ }
236
+ });
237
+ }, { threshold: 0.1 });
238
+ items.forEach(function(el) { observer.observe(el); });
239
+ })();
240
+ </script>
241
+
71
242
  {% schema %}
72
243
  {
73
244
  "name": "Pricing Table",
74
245
  "tag": "section",
75
246
  "class": "section-pricing-table",
76
247
  "settings": [
248
+ { "type": "color_scheme", "id": "color_scheme", "label": "Color Scheme", "default": "scheme-1" },
249
+ { "type": "font_picker", "id": "heading_font", "label": "Heading Font", "default": "helvetica_n4" },
250
+ { "type": "range", "id": "heading_font_size", "label": "Heading Size (px)", "min": 20, "max": 56, "step": 2, "default": 40 },
251
+ { "type": "select", "id": "heading_tag", "label": "Heading Tag", "options": [
252
+ { "value": "h1", "label": "H1" }, { "value": "h2", "label": "H2" },
253
+ { "value": "h3", "label": "H3" }, { "value": "h4", "label": "H4" }
254
+ ], "default": "h2" },
77
255
  { "type": "text", "id": "heading", "label": "Heading", "default": "Simple, Transparent Pricing" },
78
- { "type": "text", "id": "subheading", "label": "Subheading" }
256
+ { "type": "text", "id": "subheading", "label": "Subheading", "default": "Choose the plan that works for you." },
257
+ { "type": "checkbox", "id": "show_toggle", "label": "Show Monthly/Annual Toggle", "default": true },
258
+ { "type": "text", "id": "label_monthly", "label": "Monthly Label", "default": "Monthly" },
259
+ { "type": "text", "id": "label_annual", "label": "Annual Label", "default": "Annual" },
260
+ { "type": "text", "id": "annual_badge", "label": "Annual Badge Text", "default": "Save 20%" },
261
+ { "type": "checkbox", "id": "default_annual", "label": "Default to Annual", "default": false },
262
+ { "type": "text", "id": "popular_badge", "label": "Popular Badge Text", "default": "Most Popular" },
263
+ { "type": "range", "id": "padding_top", "label": "Padding Top (px)", "min": 0, "max": 160, "step": 8, "default": 80 },
264
+ { "type": "range", "id": "padding_bottom", "label": "Padding Bottom (px)", "min": 0, "max": 160, "step": 8, "default": 80 }
79
265
  ],
80
266
  "blocks": [
81
267
  {
82
268
  "type": "pricing-tier",
83
269
  "name": "Pricing Tier",
84
270
  "settings": [
85
- { "type": "text", "id": "plan_name", "label": "Plan Name", "default": "Basic" },
86
- { "type": "text", "id": "price", "label": "Price", "default": "$9" },
87
- { "type": "text", "id": "period", "label": "Period", "default": "month" },
88
- { "type": "textarea", "id": "features", "label": "Features (one per line)", "default": "Feature one\nFeature two\nFeature three" },
271
+ { "type": "text", "id": "plan_name", "label": "Plan Name", "default": "Starter" },
272
+ { "type": "text", "id": "price_monthly", "label": "Monthly Price", "default": "$9" },
273
+ { "type": "text", "id": "price_annual", "label": "Annual Price", "default": "$7" },
274
+ { "type": "text", "id": "period", "label": "Period Label", "default": "mo" },
275
+ { "type": "text", "id": "description", "label": "Short Description", "default": "Perfect for individuals" },
276
+ { "type": "textarea", "id": "features", "label": "Features (one per line)", "default": "5 projects\n10 GB storage\nEmail support" },
89
277
  { "type": "text", "id": "button_label", "label": "Button Label", "default": "Get Started" },
90
278
  { "type": "url", "id": "button_link", "label": "Button Link" },
91
- { "type": "checkbox", "id": "highlighted", "label": "Highlight this tier", "default": false }
279
+ { "type": "checkbox", "id": "highlighted", "label": "Highlight as Popular", "default": false }
92
280
  ]
93
281
  },
94
282
  { "type": "@app" }