ultimate-jekyll-manager 1.4.2 → 1.5.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 (91) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/CLAUDE-ATTRIBUTION.md +215 -0
  3. package/CLAUDE.md +7 -6
  4. package/README.md +1 -0
  5. package/dist/assets/css/pages/test/libraries/layers/index.scss +28 -0
  6. package/dist/assets/js/core/auth.js +24 -39
  7. package/dist/assets/js/modules/redirect.js +5 -4
  8. package/dist/assets/js/pages/download/index.js +1 -1
  9. package/dist/assets/js/pages/feedback/index.js +7 -1
  10. package/dist/assets/js/pages/test/libraries/layers/index.js +11 -0
  11. package/dist/assets/themes/_template/README.md +50 -0
  12. package/dist/assets/themes/_template/_config.scss +60 -0
  13. package/dist/assets/themes/_template/_theme.js +13 -4
  14. package/dist/assets/themes/_template/_theme.scss +16 -4
  15. package/dist/assets/themes/_template/css/base/_root.scss +19 -0
  16. package/dist/assets/themes/_template/css/components/_components.scss +23 -0
  17. package/dist/assets/themes/classy/README.md +18 -6
  18. package/dist/assets/themes/neobrutalism/README.md +98 -0
  19. package/dist/assets/themes/neobrutalism/_config.scss +139 -0
  20. package/dist/assets/themes/neobrutalism/_theme.js +27 -0
  21. package/dist/assets/themes/neobrutalism/_theme.scss +33 -0
  22. package/dist/assets/themes/neobrutalism/css/base/_mixins.scss +46 -0
  23. package/dist/assets/themes/neobrutalism/css/base/_root.scss +80 -0
  24. package/dist/assets/themes/neobrutalism/css/base/_typography.scss +77 -0
  25. package/dist/assets/themes/neobrutalism/css/base/_utilities.scss +25 -0
  26. package/dist/assets/themes/neobrutalism/css/components/_buttons.scss +148 -0
  27. package/dist/assets/themes/neobrutalism/css/components/_cards.scss +69 -0
  28. package/dist/assets/themes/neobrutalism/css/components/_forms.scss +88 -0
  29. package/dist/assets/themes/neobrutalism/css/components/_infinite-scroll.scss +94 -0
  30. package/dist/assets/themes/neobrutalism/css/layout/_general.scss +200 -0
  31. package/dist/assets/themes/neobrutalism/css/layout/_navigation.scss +153 -0
  32. package/dist/assets/themes/neobrutalism/js/initialize-tooltips.js +20 -0
  33. package/dist/assets/themes/neobrutalism/js/navbar-scroll.js +29 -0
  34. package/dist/assets/themes/neobrutalism/pages/index.scss +227 -0
  35. package/dist/assets/themes/neobrutalism/pages/pricing/index.scss +267 -0
  36. package/dist/assets/themes/neobrutalism/pages/test/libraries/layers/index.js +9 -0
  37. package/dist/assets/themes/neobrutalism/pages/test/libraries/layers/index.scss +7 -0
  38. package/dist/build.js +2 -5
  39. package/dist/commands/install.js +1 -1
  40. package/dist/commands/setup.js +41 -0
  41. package/dist/defaults/CLAUDE.md +5 -1
  42. package/dist/defaults/dist/_alternatives/example-competitor.md +6 -6
  43. package/dist/defaults/dist/_includes/admin/sections/sidebar.json +2 -2
  44. package/dist/defaults/dist/_includes/core/head.html +17 -0
  45. package/dist/defaults/dist/_includes/themes/classy/backend/sections/topbar.html +1 -1
  46. package/dist/defaults/dist/_includes/themes/classy/frontend/sections/footer.html +9 -6
  47. package/dist/defaults/dist/_layouts/blueprint/admin/calendar/index.html +13 -13
  48. package/dist/defaults/dist/_layouts/blueprint/admin/firebase/index.html +1 -1
  49. package/dist/defaults/dist/_layouts/blueprint/admin/users/index.html +1 -1
  50. package/dist/defaults/dist/_layouts/blueprint/admin/users/new.html +5 -5
  51. package/dist/defaults/dist/_layouts/blueprint/auth/oauth2.html +1 -1
  52. package/dist/defaults/dist/_layouts/themes/classy/backend/pages/dashboard/index.html +12 -12
  53. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/about.html +1 -1
  54. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/alternatives/alternative.html +4 -4
  55. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/alternatives/index.html +5 -5
  56. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/download.html +4 -2
  57. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/feedback.html +7 -3
  58. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/payment/confirmation.html +1 -1
  59. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/pricing.html +3 -3
  60. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/team/index.html +2 -2
  61. package/dist/defaults/dist/_layouts/themes/neobrutalism/frontend/core/base.html +31 -0
  62. package/dist/defaults/dist/_layouts/themes/neobrutalism/frontend/pages/index.html +345 -0
  63. package/dist/defaults/dist/_layouts/themes/neobrutalism/frontend/pages/pricing.html +483 -0
  64. package/dist/defaults/dist/_updates/v0.0.1.md +3 -0
  65. package/dist/defaults/dist/pages/test/account/dashboard.html +1 -1
  66. package/dist/defaults/dist/pages/test/libraries/ads.html +9 -9
  67. package/dist/defaults/dist/pages/test/libraries/bootstrap.html +6 -6
  68. package/dist/defaults/dist/pages/test/libraries/firestore.html +1 -1
  69. package/dist/defaults/dist/pages/test/libraries/form-manager.html +2 -2
  70. package/dist/defaults/dist/pages/test/libraries/layers.html +57 -0
  71. package/dist/defaults/dist/pages/test/libraries/lazy-loading.html +8 -8
  72. package/dist/defaults/dist/sitemap.html +2 -2
  73. package/dist/defaults/src/_config.yml +2 -0
  74. package/dist/defaults/test/_init.js +10 -0
  75. package/dist/gulp/tasks/defaults.js +8 -0
  76. package/dist/gulp/tasks/imagemin.js +30 -5
  77. package/dist/gulp/tasks/sass.js +43 -2
  78. package/dist/gulp/tasks/translation.js +11 -0
  79. package/dist/gulp/tasks/utils/manage-test-layers.js +97 -0
  80. package/dist/index.js +30 -4
  81. package/dist/test/runner.js +62 -0
  82. package/dist/test/suites/build/manager.test.js +11 -4
  83. package/dist/test/suites/build/mode-helpers.test.js +54 -2
  84. package/dist/utils/attach-log-file.js +24 -16
  85. package/dist/utils/mode-helpers.js +65 -40
  86. package/docs/assets.md +6 -1
  87. package/docs/environment-detection.md +85 -0
  88. package/docs/test-framework.md +48 -3
  89. package/docs/themes.md +451 -0
  90. package/package.json +2 -1
  91. package/docs/cross-context-helpers.md +0 -75
@@ -0,0 +1,483 @@
1
+ ---
2
+ ### ALL PAGES ###
3
+ layout: themes/[ site.theme.id ]/frontend/core/base
4
+
5
+ ### PAGE CONFIG ###
6
+ # Hero Section
7
+ hero:
8
+ headline: "The right plans,"
9
+ headline_accent: "for the right price"
10
+ subheadline: "Simple and affordable pricing. No hidden fees, no surprises."
11
+
12
+ # Pricing Section
13
+ pricing:
14
+ price_per_unit:
15
+ enabled: true
16
+ feature_id: "credits"
17
+ label: "credit"
18
+ definitions:
19
+ - id: "credits"
20
+ definition: "Credits are used to generate content. Each generation consumes 1 credit."
21
+ - id: "exports"
22
+ definition: "Export your creations in various formats. Watermarked exports include a small logo."
23
+ - id: "api_access"
24
+ definition: "Access our REST API to integrate with your own applications and workflows."
25
+ - id: "priority_support"
26
+ definition: "Get faster response times and dedicated support from our team."
27
+ - id: "team_collaboration"
28
+ definition: "Invite team members to collaborate on projects and share resources."
29
+ - id: "custom_branding"
30
+ definition: "Remove our branding and add your own logo to exports."
31
+ plans:
32
+ - id: "basic"
33
+ name: "Basic"
34
+ tagline: "best for getting started"
35
+ url: "/dashboard"
36
+ features:
37
+ - id: "credits"
38
+ name: "Credits"
39
+ icon: "sparkles"
40
+ - id: "exports"
41
+ name: "Exports"
42
+ icon: "download"
43
+ - id: "storage"
44
+ name: "Logo storage"
45
+ icon: "clock"
46
+ - id: "plus"
47
+ name: "Plus"
48
+ tagline: "best for individuals"
49
+ url: null
50
+ features:
51
+ - id: "credits"
52
+ name: "Credits"
53
+ icon: "sparkles"
54
+ - id: "exports"
55
+ name: "Exports"
56
+ icon: "download"
57
+ - id: "api_access"
58
+ name: "API access"
59
+ icon: "code"
60
+ - id: "priority_support"
61
+ name: "Priority support"
62
+ icon: "headset"
63
+ - id: "pro"
64
+ name: "Pro"
65
+ tagline: "best for small businesses"
66
+ url: null
67
+ popular: true
68
+ features:
69
+ - id: "credits"
70
+ name: "Credits"
71
+ icon: "sparkles"
72
+ - id: "exports"
73
+ name: "Exports"
74
+ icon: "download"
75
+ - id: "max"
76
+ name: "Max"
77
+ tagline: "best for growing businesses"
78
+ url: null
79
+ features:
80
+ - id: "credits"
81
+ name: "Credits"
82
+ icon: "sparkles"
83
+ - id: "exports"
84
+ name: "Exports"
85
+ icon: "download"
86
+ - id: "team_collaboration"
87
+ name: "Team collaboration"
88
+ icon: "users"
89
+ - id: "custom_branding"
90
+ name: "Custom branding"
91
+ icon: "palette"
92
+
93
+ # Feature Comparison Section
94
+ feature_comparison:
95
+ superheadline:
96
+ icon: "sparkles"
97
+ text: "Features"
98
+ headline: "Compare all"
99
+ headline_accent: "plans"
100
+ subheadline: "See exactly what's included in each plan"
101
+
102
+ # Social Proof Section
103
+ social_proof:
104
+ items:
105
+ - number: "5M"
106
+ label: "Customers"
107
+ color: "blue"
108
+ - number: "#1"
109
+ label: "Product of the month"
110
+ color: "pink"
111
+ - number: "4.8"
112
+ label: "Capterra"
113
+ color: "yellow"
114
+ - number: "4.8"
115
+ label: "G2"
116
+ color: "green"
117
+
118
+ # CTA Section
119
+ cta:
120
+ superheadline:
121
+ icon: "comments"
122
+ text: "Support"
123
+ headline: "Need help finding the right plan for your"
124
+ headline_accent: "needs?"
125
+ subheadline: "Talk to our support team 24/7"
126
+ button:
127
+ text: "Talk to us"
128
+ icon: "headset"
129
+ href: "/contact"
130
+
131
+ # FAQs Section
132
+ faqs:
133
+ superheadline:
134
+ icon: "messages-question"
135
+ text: "FAQs"
136
+ headline: "Frequently asked"
137
+ headline_accent: "questions"
138
+ subheadline: "Everything you need to know about {{ site.brand.name }} billing & subscriptions."
139
+ items:
140
+ - question: "Can I cancel at any time?"
141
+ answer: "Yes, you can cancel anytime, no questions asked. However, we would highly appreciate it if you could give us some feedback so we can improve."
142
+ - question: "Is there a free trial?"
143
+ answer: "Yes, there is a 14-day free trial of the paid plans. You can cancel your subscription at any time during the trial period for a full refund."
144
+ - question: "What is your refund policy?"
145
+ answer: "We offer a 14-day free trial of the premium plans. You can cancel any time during your trial for a full refund. After the trial period, you can cancel and you may receive a prorated refund for the remaining time on your subscription."
146
+ ---
147
+
148
+ {% comment %}
149
+ NEOBRUTALISM PRICING
150
+ Same data contract + price-resolution Liquid as the classy pricing page, but a
151
+ neobrutalist STRUCTURE: ink-framed plan blocks where the popular plan is an
152
+ oversized accent block, a hard square billing toggle, oversized color-block
153
+ social-proof, and a full-bleed CTA. See docs/themes.md.
154
+ {% endcomment %}
155
+
156
+ <!-- ============================================ -->
157
+ <!-- HERO -->
158
+ <!-- ============================================ -->
159
+ <section class="pricing-hero">
160
+ <div class="container">
161
+ <span class="kicker mb-4">{% uj_icon "tag", "me-1" %}Pricing</span>
162
+ <h1 class="pricing-title">
163
+ {{ page.resolved.hero.headline }}
164
+ <span class="text-accent">{{ page.resolved.hero.headline_accent }}</span>
165
+ </h1>
166
+ {% iftruthy page.resolved.hero.subheadline %}
167
+ <p class="fs-4 fw-medium mb-0">{{ page.resolved.hero.subheadline }}</p>
168
+ {% endiftruthy %}
169
+ </div>
170
+ </section>
171
+
172
+ <!-- ============================================ -->
173
+ <!-- PLANS -->
174
+ <!-- ============================================ -->
175
+ <section class="pricing-plans pt-0">
176
+ <div class="container">
177
+ <!-- Billing toggle: hard square segmented control -->
178
+ <div class="billing-toggle" role="group" aria-label="Billing toggle">
179
+ <input type="radio" class="btn-check" name="billing" id="monthly" autocomplete="off" data-billing="monthly">
180
+ <label class="billing-option" for="monthly">Monthly</label>
181
+ <input type="radio" class="btn-check" name="billing" id="annually" autocomplete="off" checked data-billing="annually">
182
+ <label class="billing-option" for="annually">Annually <span class="billing-save">up to 20% off</span></label>
183
+ </div>
184
+
185
+ <p class="text-center fw-medium mb-5">
186
+ {% uj_icon "shield-check", "me-1 text-success" %}
187
+ Every paid plan backed by a 7-day money-back guarantee
188
+ </p>
189
+
190
+ {% assign plan_count = page.resolved.pricing.plans | size %}
191
+
192
+ {% comment %} Detect common features across ALL plans (same logic as classy) {% endcomment %}
193
+ {% assign common_feature_ids = "" | split: "," %}
194
+ {% if plan_count > 0 %}
195
+ {% assign first_plan = page.resolved.pricing.plans[0] %}
196
+ {% for first_feature in first_plan.features %}
197
+ {% assign is_common = true %}
198
+ {% for check_plan in page.resolved.pricing.plans %}
199
+ {% assign found_in_plan = false %}
200
+ {% for check_feature in check_plan.features %}
201
+ {% if check_feature.id == first_feature.id %}{% assign found_in_plan = true %}{% break %}{% endif %}
202
+ {% endfor %}
203
+ {% unless found_in_plan %}{% assign is_common = false %}{% break %}{% endunless %}
204
+ {% endfor %}
205
+ {% if is_common %}{% assign common_feature_ids = common_feature_ids | push: first_feature.id %}{% endif %}
206
+ {% endfor %}
207
+ {% endif %}
208
+
209
+ <div class="pricing-plan-grid">
210
+ {% for plan in page.resolved.pricing.plans %}
211
+ {% comment %} Look up matching config product (same as classy) {% endcomment %}
212
+ {% assign _config_product = nil %}
213
+ {% for p in site.web_manager.payment.products %}
214
+ {% if p.id == plan.id %}{% assign _config_product = p %}{% break %}{% endif %}
215
+ {% endfor %}
216
+
217
+ {% if plan.pricing.monthly or plan.pricing.monthly == 0 %}
218
+ {% assign _plan_monthly = plan.pricing.monthly %}
219
+ {% elsif _config_product.prices.monthly or _config_product.prices.monthly == 0 %}
220
+ {% assign _plan_monthly = _config_product.prices.monthly %}
221
+ {% else %}{% assign _plan_monthly = 0 %}{% endif %}
222
+
223
+ {% if plan.pricing.annually or plan.pricing.annually == 0 %}
224
+ {% assign _plan_annually = plan.pricing.annually %}
225
+ {% elsif _config_product.prices.annually or _config_product.prices.annually == 0 %}
226
+ {% assign _plan_annually = _config_product.prices.annually %}
227
+ {% else %}{% assign _plan_annually = 0 %}{% endif %}
228
+
229
+ <article class="card pricing-plan {% if plan.popular %}pricing-plan--popular{% endif %}">
230
+ {% if plan.popular %}
231
+ <span class="pricing-plan-flag">Most Popular</span>
232
+ {% endif %}
233
+
234
+ <h3 class="pricing-plan-name">{{ plan.name }}</h3>
235
+ <p class="pricing-plan-tagline">{{ plan.tagline }}</p>
236
+
237
+ <!-- Price -->
238
+ <div class="pricing-plan-price">
239
+ {% if _plan_monthly == 0 %}
240
+ <span class="pricing-plan-amount">Free</span>
241
+ {% else %}
242
+ <span class="pricing-plan-currency">$</span><span class="pricing-plan-amount amount" data-monthly="{{ _plan_monthly }}" data-annually="{{ _plan_annually | divided_by: 12 | round }}">{{ _plan_annually | divided_by: 12 | round }}</span><span class="pricing-plan-per">/mo</span>
243
+ {% endif %}
244
+ </div>
245
+
246
+ {% if page.resolved.pricing.price_per_unit.enabled %}
247
+ {% comment %} Resolve the per-unit value; only render if it's a usable positive number {% endcomment %}
248
+ {% assign _ppu_value = nil %}
249
+ {% if _plan_monthly > 0 %}
250
+ {% for feature in plan.features %}
251
+ {% if feature.id == page.resolved.pricing.price_per_unit.feature_id %}
252
+ {% assign _ppu_value = feature.value %}
253
+ {% if _config_product and _ppu_value == nil %}
254
+ {% for _lim in _config_product.limits %}{% if _lim[0] == feature.id %}{% assign _ppu_value = _lim[1] %}{% break %}{% endif %}{% endfor %}
255
+ {% endif %}
256
+ {% endif %}
257
+ {% endfor %}
258
+ {% endif %}
259
+ <p class="pricing-plan-ppu">
260
+ {% if _plan_monthly > 0 and _ppu_value and _ppu_value > 0 %}
261
+ {% assign monthly_price_per_unit = _plan_monthly | times: 1.0 | divided_by: _ppu_value | round: 2 %}
262
+ {% assign annual_monthly_price = _plan_annually | divided_by: 12.0 %}
263
+ {% assign annual_price_per_unit = annual_monthly_price | divided_by: _ppu_value | round: 2 %}
264
+ <span class="price-per-unit" data-monthly="${{ monthly_price_per_unit }}" data-annually="${{ annual_price_per_unit }}">${{ annual_price_per_unit }}</span> per {{ page.resolved.pricing.price_per_unit.label }}
265
+ {% elsif _plan_monthly == 0 %}
266
+ Perfect for trying out
267
+ {% endif %}
268
+ </p>
269
+ {% endif %}
270
+
271
+ <!-- CTA: all paid plans use the solid blue button; only the FREE plan
272
+ uses the outline variant so it reads as the entry-level option. -->
273
+ <div class="d-grid mb-3">
274
+ {% if _plan_monthly == 0 %}{% assign _cta_class = "btn-outline-primary" %}{% else %}{% assign _cta_class = "btn-primary" %}{% endif %}
275
+ {% iftruthy plan.url %}
276
+ <a href="{{ plan.url }}" class="btn {{ _cta_class }} btn-lg fw-bold">
277
+ {% if _plan_monthly == 0 %}Get started{% elsif plan.trial.days > 0 %}Get free trial{% else %}Get started{% endif %}
278
+ </a>
279
+ {% endiftruthy %}
280
+ {% iffalsy plan.url %}
281
+ <button class="btn {{ _cta_class }} btn-lg fw-bold" data-plan-id="{{ plan.id }}">
282
+ {% if plan.trial.days > 0 %}Get free trial{% else %}Get started{% endif %}
283
+ </button>
284
+ {% endiffalsy %}
285
+ </div>
286
+
287
+ <!-- Billing info -->
288
+ <p class="pricing-plan-billing">
289
+ {% if _plan_monthly == 0 %}
290
+ No credit card required
291
+ {% else %}
292
+ <span class="billing-info" data-monthly="Billed ${{ _plan_monthly | uj_commaify }} monthly" data-annually="Billed ${{ _plan_annually | uj_commaify }} annually">
293
+ Billed ${{ _plan_annually | uj_commaify }} annually
294
+ </span>
295
+ {% endif %}
296
+ </p>
297
+
298
+ <!-- Guarantee (every plan) -->
299
+ <p class="pricing-plan-guarantee">
300
+ {% if _plan_monthly > 0 %}
301
+ {% uj_icon "shield-check", "me-1 text-success" %}7-day money-back guarantee
302
+ {% else %}
303
+ {% uj_icon "rocket", "me-1 text-success" %}Upgrade any time
304
+ {% endif %}
305
+ </p>
306
+
307
+ <hr class="pricing-plan-rule">
308
+
309
+ {% comment %}
310
+ Feature list — same tier-inheritance logic as classy:
311
+ 1. Common features (vary by plan, shown on every card)
312
+ 2. Basic (first plan): "What you get:" + its unique features
313
+ 3. Other plans: "Everything in <prev>, and more:" + only the ADDED features
314
+ Helpers below render a value + the name (wrapped in a tooltip span when the
315
+ feature has a definition).
316
+ {% endcomment %}
317
+
318
+ <!-- 1. Common features -->
319
+ <ul class="pricing-plan-features">
320
+ {% for feature in plan.features %}
321
+ {% if common_feature_ids contains feature.id %}
322
+ {% assign _feature_value = feature.value %}
323
+ {% if _config_product and _feature_value == nil %}
324
+ {% assign _config_limit = nil %}{% for _lim in _config_product.limits %}{% if _lim[0] == feature.id %}{% assign _config_limit = _lim[1] %}{% break %}{% endif %}{% endfor %}
325
+ {% if _config_limit == -1 %}{% assign _feature_value = "Unlimited" %}{% elsif _config_limit %}{% assign _feature_value = _config_limit %}{% endif %}
326
+ {% endif %}
327
+ {% assign feature_definition = nil %}
328
+ {% for def in page.resolved.pricing.definitions %}{% if def.id == feature.id %}{% assign feature_definition = def.definition %}{% break %}{% endif %}{% endfor %}
329
+ <li>
330
+ <span class="pricing-plan-feature-icon">{% uj_icon feature.icon, "fa-sm" %}</span>
331
+ <span>
332
+ {% if _feature_value == "Unlimited" %}Unlimited{% elsif _feature_value == "24/7" %}{{ _feature_value }}{% elsif _feature_value == true or _feature_value == "Included" or _feature_value == "Available" or _feature_value == "Full" %}{% else %}{{ _feature_value | uj_commaify }}{% endif %}
333
+ {% iftruthy feature_definition %}<span class="text-decoration-underline text-decoration-dotted cursor-help" data-bs-toggle="tooltip" data-bs-title="{{ feature_definition }}">{{ feature.name }}</span>{% endiftruthy %}
334
+ {% iffalsy feature_definition %}{{ feature.name }}{% endiffalsy %}
335
+ </span>
336
+ </li>
337
+ {% endif %}
338
+ {% endfor %}
339
+ </ul>
340
+
341
+ {% comment %} Does this plan add any non-common (unique) features? {% endcomment %}
342
+ {% assign has_additional = false %}
343
+ {% for feature in plan.features %}{% unless common_feature_ids contains feature.id %}{% assign has_additional = true %}{% break %}{% endunless %}{% endfor %}
344
+
345
+ <!-- 2/3. Inheritance label + the plan's additional features -->
346
+ {% if forloop.index == 1 %}
347
+ {% if has_additional %}
348
+ <p class="pricing-plan-inherit">What you get:</p>
349
+ {% endif %}
350
+ {% else %}
351
+ {% assign _prev_index = forloop.index0 | minus: 1 %}
352
+ {% assign _prev_plan = page.resolved.pricing.plans[_prev_index] %}
353
+ <p class="pricing-plan-inherit">Everything in <strong>{{ _prev_plan.name }}</strong>{% if has_additional %}, and more:{% endif %}</p>
354
+ {% endif %}
355
+
356
+ {% if has_additional %}
357
+ <ul class="pricing-plan-features">
358
+ {% for feature in plan.features %}
359
+ {% unless common_feature_ids contains feature.id %}
360
+ {% assign _feature_value = feature.value %}
361
+ {% if _config_product and _feature_value == nil %}
362
+ {% assign _config_limit = nil %}{% for _lim in _config_product.limits %}{% if _lim[0] == feature.id %}{% assign _config_limit = _lim[1] %}{% break %}{% endif %}{% endfor %}
363
+ {% if _config_limit == -1 %}{% assign _feature_value = "Unlimited" %}{% elsif _config_limit %}{% assign _feature_value = _config_limit %}{% endif %}
364
+ {% endif %}
365
+ {% assign feature_definition = nil %}
366
+ {% for def in page.resolved.pricing.definitions %}{% if def.id == feature.id %}{% assign feature_definition = def.definition %}{% break %}{% endif %}{% endfor %}
367
+ <li>
368
+ <span class="pricing-plan-feature-icon">{% uj_icon feature.icon, "fa-sm" %}</span>
369
+ <span>
370
+ {% if _feature_value == "Unlimited" %}Unlimited{% elsif _feature_value == "24/7" %}{{ _feature_value }}{% elsif _feature_value == true or _feature_value == "Included" or _feature_value == "Available" or _feature_value == "Full" %}{% else %}{{ _feature_value | uj_commaify }}{% endif %}
371
+ {% iftruthy feature_definition %}<span class="text-decoration-underline text-decoration-dotted cursor-help" data-bs-toggle="tooltip" data-bs-title="{{ feature_definition }}">{{ feature.name }}</span>{% endiftruthy %}
372
+ {% iffalsy feature_definition %}{{ feature.name }}{% endiffalsy %}
373
+ </span>
374
+ </li>
375
+ {% endunless %}
376
+ {% endfor %}
377
+ </ul>
378
+ {% endif %}
379
+ </article>
380
+ {% endfor %}
381
+ </div>
382
+
383
+ <!-- Enterprise block -->
384
+ <div class="card enterprise-panel">
385
+ <div>
386
+ <h3 class="enterprise-panel-title">Enterprise</h3>
387
+ <p class="mb-0 fw-medium">Custom solutions for large organizations. Advanced security and flexible pricing based on your needs.</p>
388
+ </div>
389
+ <button class="btn btn-primary btn-lg fw-bold flex-shrink-0" data-plan-id="enterprise">
390
+ {% uj_icon "envelope", "me-2" %}Contact us
391
+ </button>
392
+ </div>
393
+ </div>
394
+ </section>
395
+
396
+ <!-- ============================================ -->
397
+ <!-- SOCIAL PROOF — oversized color blocks -->
398
+ <!-- ============================================ -->
399
+ <section class="stats">
400
+ <div class="container">
401
+ <div class="stats-grid">
402
+ {% for item in page.resolved.social_proof.items %}
403
+ {% assign stat_bg = "text-bg-primary" %}
404
+ {% case item.color %}
405
+ {% when "pink" %}{% assign stat_bg = "text-bg-secondary" %}
406
+ {% when "green" %}{% assign stat_bg = "text-bg-success" %}
407
+ {% when "yellow" %}{% assign stat_bg = "text-bg-warning" %}
408
+ {% when "info" %}{% assign stat_bg = "text-bg-info" %}
409
+ {% else %}{% assign stat_bg = "text-bg-primary" %}
410
+ {% endcase %}
411
+ <div class="stat-block {{ stat_bg }}">
412
+ <span class="stat-block-num">{{ item.number }}</span>
413
+ <span class="stat-block-label">{{ item.label }}</span>
414
+ </div>
415
+ {% endfor %}
416
+ </div>
417
+ </div>
418
+ </section>
419
+
420
+ <!-- ============================================ -->
421
+ <!-- FAQ -->
422
+ <!-- ============================================ -->
423
+ <section class="faq">
424
+ <div class="container">
425
+ <div class="row justify-content-center">
426
+ <div class="col-lg-9">
427
+ <header class="section-head mb-5">
428
+ {% iftruthy page.resolved.faqs.superheadline.text %}
429
+ <span class="kicker mb-3">{% uj_icon page.resolved.faqs.superheadline.icon, "me-1" %}{{ page.resolved.faqs.superheadline.text }}</span>
430
+ {% endiftruthy %}
431
+ <h2 class="section-title">
432
+ {{ page.resolved.faqs.headline }}
433
+ <span class="text-accent">{{ page.resolved.faqs.headline_accent }}</span>
434
+ </h2>
435
+ </header>
436
+
437
+ {% if page.resolved.faqs.items %}
438
+ <div class="accordion" id="faqAccordion">
439
+ {% for faq in page.resolved.faqs.items %}
440
+ <div class="accordion-item mb-3">
441
+ <h2 class="accordion-header">
442
+ <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faq{{ forloop.index }}" aria-expanded="false" aria-controls="faq{{ forloop.index }}">
443
+ <span class="fw-bold">{{ faq.question }}</span>
444
+ </button>
445
+ </h2>
446
+ <div id="faq{{ forloop.index }}" class="accordion-collapse collapse" data-bs-parent="#faqAccordion">
447
+ <div class="accordion-body">{{ faq.answer }}</div>
448
+ </div>
449
+ </div>
450
+ {% endfor %}
451
+ </div>
452
+ {% endif %}
453
+ </div>
454
+ </div>
455
+ </div>
456
+ </section>
457
+
458
+ <!-- ============================================ -->
459
+ <!-- CTA -->
460
+ <!-- ============================================ -->
461
+ <section class="cta">
462
+ <div class="container">
463
+ <div class="cta-panel">
464
+ {% iftruthy page.resolved.cta.superheadline.text %}
465
+ <span class="kicker kicker--invert mb-4">{% uj_icon page.resolved.cta.superheadline.icon, "me-1" %}{{ page.resolved.cta.superheadline.text }}</span>
466
+ {% endiftruthy %}
467
+ <h2 class="cta-title">
468
+ {{ page.resolved.cta.headline }}
469
+ <span class="text-accent">{{ page.resolved.cta.headline_accent }}</span>
470
+ </h2>
471
+ {% iftruthy page.resolved.cta.subheadline %}
472
+ <p class="cta-desc">{{ page.resolved.cta.subheadline }}</p>
473
+ {% endiftruthy %}
474
+ <div class="d-flex flex-wrap gap-3 justify-content-center">
475
+ <a href="{{ page.resolved.cta.button.href }}" class="btn btn-warning btn-lg">
476
+ {% uj_icon page.resolved.cta.button.icon, "me-2" %}{{ page.resolved.cta.button.text }}
477
+ </a>
478
+ </div>
479
+ </div>
480
+ </div>
481
+ </section>
482
+
483
+ {{ content | uj_content_format }}
@@ -2,6 +2,9 @@
2
2
  ### ALL PAGES ###
3
3
  layout: blueprint/updates/update
4
4
 
5
+ ### PAGE CONFIG ###
6
+ draft: true # Hide from listing and sitemap (only visible in development)
7
+
5
8
  ### UPDATE CONFIG ###
6
9
  update:
7
10
  version: "0.0.1"
@@ -7,7 +7,7 @@ permalink: /test/account/dashboard
7
7
  meta:
8
8
  title: "Dashboard account test page"
9
9
  description: "Test"
10
- breadcrumb: "Dashboard Test page"
10
+ breadcrumb: "Dashboard test page"
11
11
  index: false
12
12
 
13
13
  ### WEB MANAGER CONFIG ###
@@ -7,9 +7,9 @@ permalink: /test/libraries/ads
7
7
  sitemap:
8
8
  include: false
9
9
  meta:
10
- title: "AdSense Test Page"
10
+ title: "AdSense test page"
11
11
  description: "Test page for demonstrating AdSense ad units"
12
- breadcrumb: "AdSense Test"
12
+ breadcrumb: "AdSense test"
13
13
  index: false
14
14
  ---
15
15
 
@@ -17,12 +17,12 @@ meta:
17
17
  <div class="container">
18
18
  <div class="row">
19
19
  <div class="col-lg-8 mx-auto">
20
- <h1 class="h2 mb-4">AdSense Test Page</h1>
20
+ <h1 class="h2 mb-4">AdSense test page</h1>
21
21
  <p class="lead mb-5">This page demonstrates different AdSense ad unit types and lazy loading behavior.</p>
22
22
 
23
23
  <!-- Display Ad -->
24
24
  <section>
25
- <h2 class="h4 mb-3">1. Display Ad</h2>
25
+ <h2 class="h4 mb-3">1. Display ad</h2>
26
26
  {% include /modules/adunits/adsense.html type="display" %}
27
27
  </section>
28
28
 
@@ -30,7 +30,7 @@ meta:
30
30
 
31
31
  <!-- In-Article Ad -->
32
32
  <section>
33
- <h2 class="h4 mb-3">2. In-Article Ad</h2>
33
+ <h2 class="h4 mb-3">2. In-article ad</h2>
34
34
  {% include /modules/adunits/adsense.html type="in-article" %}
35
35
  </section>
36
36
 
@@ -38,7 +38,7 @@ meta:
38
38
 
39
39
  <!-- In-Feed Ad (Image Above) -->
40
40
  <section>
41
- <h2 class="h4 mb-3">3. In-Feed Ad (Image Above)</h2>
41
+ <h2 class="h4 mb-3">3. In-feed ad (image above)</h2>
42
42
  {% include /modules/adunits/adsense.html type="in-feed" layout="image-above" %}
43
43
  </section>
44
44
 
@@ -46,7 +46,7 @@ meta:
46
46
 
47
47
  <!-- In-Feed Ad (Image Side) -->
48
48
  <section>
49
- <h2 class="h4 mb-3">4. In-Feed Ad (Image Side)</h2>
49
+ <h2 class="h4 mb-3">4. In-feed ad (image side)</h2>
50
50
  {% include /modules/adunits/adsense.html type="in-feed" layout="image-side" %}
51
51
  </section>
52
52
 
@@ -54,7 +54,7 @@ meta:
54
54
 
55
55
  <!-- Multiplex Ad -->
56
56
  <section>
57
- <h2 class="h4 mb-3">5. Multiplex Ad</h2>
57
+ <h2 class="h4 mb-3">5. Multiplex ad</h2>
58
58
  {% include /modules/adunits/adsense.html type="multiplex" %}
59
59
  </section>
60
60
 
@@ -63,7 +63,7 @@ meta:
63
63
 
64
64
  <!-- Lazy loaded display ad -->
65
65
  <section>
66
- <h2 class="h4 mb-3">6. Lazy Loaded Display Ad (Below the Fold)</h2>
66
+ <h2 class="h4 mb-3">6. Lazy loaded display ad (below the fold)</h2>
67
67
  <p class="text-muted mb-3">This ad should only load when scrolled into view.</p>
68
68
  {% include /modules/adunits/adsense.html type="display" %}
69
69
  </section>
@@ -24,10 +24,10 @@ meta:
24
24
  <h3 class="mb-3">Rainbow gradient effects</h3>
25
25
  <h1 class="text-gradient-rainbow">Static rainbow text</h1>
26
26
  <h2 class="text-gradient-rainbow gradient-animated">Animated rainbow text</h2>
27
- <p class="fs-4">Button Examples:</p>
27
+ <p class="fs-4">Button examples:</p>
28
28
  <button class="btn btn-gradient-rainbow me-2">Static rainbow button</button>
29
29
  <button class="btn btn-gradient-rainbow gradient-animated">Animated rainbow button</button>
30
- <p class="fs-4 mt-3">Background Example:</p>
30
+ <p class="fs-4 mt-3">Background example:</p>
31
31
  <div class="p-3 bg-gradient-rainbow gradient-animated text-light rounded">Animated rainbow background</div>
32
32
 
33
33
  <h3 class="mt-4 mb-3">Core animations</h3>
@@ -151,7 +151,7 @@ meta:
151
151
 
152
152
  <!-- Classy Theme Specific -->
153
153
  <section class="p-4 text-light rounded">
154
- <h2 class="border-bottom border-light pb-2 mb-4">✨ Classy Theme Components</h2>
154
+ <h2 class="border-bottom border-light pb-2 mb-4">✨ Classy theme components</h2>
155
155
 
156
156
  <h3 class="mb-3">Glassy effects</h3>
157
157
  <div class="p-5 bg-gradient-rainbow gradient-animated rounded mb-4">
@@ -312,7 +312,7 @@ meta:
312
312
  <p class="fs-5">Font size 5</p>
313
313
  <p class="fs-6">Font size 6</p>
314
314
 
315
- <h3 class="mt-4 mb-3">Font Weight & Style</h3>
315
+ <h3 class="mt-4 mb-3">Font weight & style</h3>
316
316
  <p class="fw-bold">Bold text</p>
317
317
  <p class="fw-bolder">Bolder weight text</p>
318
318
  <p class="fw-semibold">Semibold weight text</p>
@@ -604,7 +604,7 @@ meta:
604
604
  <input class="form-control" type="file" id="formFile">
605
605
  </div>
606
606
 
607
- <h3 class="mt-4 mb-3">Form & Button Size Comparison</h3>
607
+ <h3 class="mt-4 mb-3">Form & button size comparison</h3>
608
608
  <div class="card">
609
609
  <div class="card-body">
610
610
  <div class="row mb-3">
@@ -853,7 +853,7 @@ meta:
853
853
  </ul>
854
854
  </div>
855
855
  <div class="col-md-6">
856
- <h3 class="mb-3">List Group with Badges</h3>
856
+ <h3 class="mb-3">List group with badges</h3>
857
857
  <ul class="list-group">
858
858
  <li class="list-group-item d-flex justify-content-between align-items-center">
859
859
  A list item
@@ -25,7 +25,7 @@ sitemap:
25
25
  </style>
26
26
  </head>
27
27
  <body>
28
- <h1>Firestore Version + Transport Test</h1>
28
+ <h1>Firestore version + transport test</h1>
29
29
  <div id="ua"></div>
30
30
  <div id="status">Loading...</div>
31
31
  <div id="sw-status" style="color: #f80; margin-bottom: 12px;"></div>
@@ -15,7 +15,7 @@ meta:
15
15
 
16
16
  <section>
17
17
  <div class="container">
18
- <h1 class="mb-4">FormManager Test Page</h1>
18
+ <h1 class="mb-4">FormManager test page</h1>
19
19
  <p class="text-muted mb-5">Testing different configurations of the FormManager library.</p>
20
20
 
21
21
  <div class="row g-4">
@@ -204,7 +204,7 @@ meta:
204
204
  <div class="row">
205
205
  <!-- Global settings (no data-input-group = always included) -->
206
206
  <div class="col-md-4">
207
- <h6 class="text-muted mb-3">Global Settings <span class="badge bg-secondary">Always included</span></h6>
207
+ <h6 class="text-muted mb-3">Global settings <span class="badge bg-secondary">Always included</span></h6>
208
208
  <div class="mb-3">
209
209
  <label for="groups-name" class="form-label">settings.name</label>
210
210
  <input type="text" class="form-control" id="groups-name" name="settings.name" value="My project" disabled>