ultimate-jekyll-manager 1.7.2 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +69 -1
- package/CLAUDE.md +36 -15
- package/README.md +4 -2
- package/TODO-AUTH-TESTING.md +1 -1
- package/dist/assets/themes/newsflash/README.md +58 -0
- package/dist/assets/themes/newsflash/_config.scss +138 -0
- package/dist/assets/themes/newsflash/_theme.js +27 -0
- package/dist/assets/themes/newsflash/_theme.scss +37 -0
- package/dist/assets/themes/newsflash/css/base/_mixins.scss +50 -0
- package/dist/assets/themes/newsflash/css/base/_root.scss +134 -0
- package/dist/assets/themes/newsflash/css/base/_typography.scss +49 -0
- package/dist/assets/themes/newsflash/css/base/_utilities.scss +58 -0
- package/dist/assets/themes/newsflash/css/components/_badges.scss +65 -0
- package/dist/assets/themes/newsflash/css/components/_buttons.scss +139 -0
- package/dist/assets/themes/newsflash/css/components/_cards.scss +52 -0
- package/dist/assets/themes/newsflash/css/components/_editorial.scss +182 -0
- package/dist/assets/themes/newsflash/css/components/_forms.scss +75 -0
- package/dist/assets/themes/newsflash/css/components/_infinite-scroll.scss +102 -0
- package/dist/assets/themes/newsflash/css/components/_panels.scss +91 -0
- package/dist/assets/themes/newsflash/css/components/_ticker.scss +70 -0
- package/dist/assets/themes/newsflash/css/layout/_general.scss +264 -0
- package/dist/assets/themes/newsflash/css/layout/_navigation.scss +164 -0
- package/dist/assets/themes/newsflash/js/initialize-tooltips.js +20 -0
- package/dist/assets/themes/newsflash/js/masthead-scroll.js +29 -0
- package/dist/assets/themes/newsflash/pages/404/index.scss +27 -0
- package/dist/assets/themes/newsflash/pages/about/index.scss +70 -0
- package/dist/assets/themes/newsflash/pages/blog/index.scss +17 -0
- package/dist/assets/themes/newsflash/pages/blog/post.js +29 -0
- package/dist/assets/themes/newsflash/pages/blog/post.scss +164 -0
- package/dist/assets/themes/newsflash/pages/index.scss +159 -0
- package/dist/assets/themes/newsflash/pages/pricing/index.scss +194 -0
- package/dist/assets/themes/newsflash/pages/test/libraries/layers/index.js +9 -0
- package/dist/assets/themes/newsflash/pages/test/libraries/layers/index.scss +7 -0
- package/dist/commands/blogify.js +6 -3
- package/dist/commands/test.js +34 -5
- package/dist/defaults/CLAUDE.md +17 -4
- package/dist/defaults/dist/_includes/core/pricing/resolve-plan.html +59 -0
- package/dist/defaults/dist/_includes/themes/classy/frontend/sections/footer.html +20 -3
- package/dist/defaults/dist/_layouts/themes/classy/admin/core/minimal-viewport-locked.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/admin/core/minimal.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/pricing.html +5 -40
- package/dist/defaults/dist/_layouts/themes/neobrutalism/frontend/pages/pricing.html +33 -34
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/core/base.html +61 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/404.html +86 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/about.html +353 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/categories/category.html +105 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/categories/index.html +93 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/index.html +373 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/post.html +289 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/tags/index.html +90 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/tags/tag.html +107 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/contact.html +340 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/index.html +522 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/pricing.html +485 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/team/index.html +207 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/team/member.html +134 -0
- package/dist/defaults/test/README.md +4 -0
- package/dist/gulp/tasks/jekyll.js +4 -2
- package/dist/test/runner.js +50 -3
- package/dist/test/suites/build/attach-log-file.test.js +102 -0
- package/dist/test/suites/build/theme-contract.test.js +173 -0
- package/dist/test/utils/extended-mode-warning.js +13 -0
- package/dist/utils/attach-log-file.js +70 -43
- package/docs/appearance.md +1 -0
- package/docs/assets.md +9 -0
- package/docs/audit.md +78 -7
- package/docs/build-system.md +57 -0
- package/docs/common-mistakes.md +15 -0
- package/docs/{project-structure.md → directory-structure.md} +1 -1
- package/docs/environment-detection.md +1 -1
- package/docs/javascript-libraries.md +38 -1
- package/docs/layouts-and-pages.md +146 -0
- package/docs/local-development.md +1 -8
- package/docs/logging.md +30 -0
- package/docs/migration.md +131 -0
- package/docs/no-inline-scripts.md +304 -0
- package/docs/purgecss.md +164 -0
- package/docs/seo.md +131 -4
- package/docs/templating.md +23 -0
- package/docs/test-boot-layer.md +1 -1
- package/docs/test-framework.md +56 -8
- package/docs/themes.md +254 -13
- package/logs/test.log +111 -0
- package/package.json +9 -8
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
---
|
|
2
|
+
### ALL PAGES ###
|
|
3
|
+
layout: themes/[ site.theme.id ]/frontend/core/base
|
|
4
|
+
|
|
5
|
+
### PAGE CONFIG ###
|
|
6
|
+
# Hero Section — the front-page lead. News voice: the brand IS the publication.
|
|
7
|
+
hero:
|
|
8
|
+
tagline: "{{ site.brand.name }} — independent journalism"
|
|
9
|
+
headline: "News with a"
|
|
10
|
+
headline_accent: "pulse"
|
|
11
|
+
description: "Sharp reporting and zero noise — the stories that matter, delivered before your coffee gets cold."
|
|
12
|
+
primary_button:
|
|
13
|
+
text: "Read the latest"
|
|
14
|
+
icon: "bolt"
|
|
15
|
+
href: "/blog"
|
|
16
|
+
secondary_button:
|
|
17
|
+
text: "Get the newsletter"
|
|
18
|
+
icon: "envelope"
|
|
19
|
+
href: "#signup"
|
|
20
|
+
|
|
21
|
+
# The Latest — the front-page feed (posts-driven; newsflash-specific section)
|
|
22
|
+
latest:
|
|
23
|
+
superheadline:
|
|
24
|
+
icon: "bolt"
|
|
25
|
+
text: "The latest"
|
|
26
|
+
view_all:
|
|
27
|
+
text: "View the firehose"
|
|
28
|
+
href: "/blog"
|
|
29
|
+
|
|
30
|
+
# More to Chew On — extra stories before the big read (posts-driven)
|
|
31
|
+
more_stories:
|
|
32
|
+
superheadline:
|
|
33
|
+
icon: "newspaper"
|
|
34
|
+
text: "More to chew on"
|
|
35
|
+
|
|
36
|
+
# The Rundown — the newsroom's three-step playbook (newsflash-specific section)
|
|
37
|
+
rundown:
|
|
38
|
+
superheadline:
|
|
39
|
+
icon: "list"
|
|
40
|
+
text: "The rundown"
|
|
41
|
+
headline: "Journalism worth your"
|
|
42
|
+
headline_accent: "morning"
|
|
43
|
+
subheadline: "What you get from the {{ site.brand.name }} newsroom every single day"
|
|
44
|
+
items:
|
|
45
|
+
- title: "Original reporting"
|
|
46
|
+
description: "Stories researched and written by people who pick up the phone — not rewrites of someone else's scoop."
|
|
47
|
+
- title: "The daily briefing"
|
|
48
|
+
description: "The five stories that actually matter, distilled into a five-minute read and delivered before sunrise."
|
|
49
|
+
- title: "Deep dives"
|
|
50
|
+
description: "Long-form features that follow the money, the people, and the consequences long after the headlines move on."
|
|
51
|
+
|
|
52
|
+
# Newsletter Rail (sidebar signup)
|
|
53
|
+
newsletter:
|
|
54
|
+
headline: "{{ site.brand.name }}, daily."
|
|
55
|
+
subheadline: "One ridiculously good email every morning. The stories that matter, minus the noise."
|
|
56
|
+
button:
|
|
57
|
+
text: "Join"
|
|
58
|
+
form:
|
|
59
|
+
placeholder: "you@example.com"
|
|
60
|
+
disclaimer: "Free forever. Unsubscribe anytime."
|
|
61
|
+
|
|
62
|
+
# The Desks — coverage areas (newsflash-specific section)
|
|
63
|
+
desks:
|
|
64
|
+
superheadline:
|
|
65
|
+
icon: "newspaper"
|
|
66
|
+
text: "The desks"
|
|
67
|
+
headline: "Coverage with"
|
|
68
|
+
headline_accent: "teeth"
|
|
69
|
+
subheadline: "Three desks, one standard: report it right, write it sharp."
|
|
70
|
+
cta_button:
|
|
71
|
+
text: "Browse all stories"
|
|
72
|
+
icon: "arrow-right"
|
|
73
|
+
href: "/blog"
|
|
74
|
+
items:
|
|
75
|
+
- title: "Tech"
|
|
76
|
+
description: "The machines, the makers, and the money rewiring how we live and work."
|
|
77
|
+
icon: "microchip"
|
|
78
|
+
href: "/blog/categories/tech"
|
|
79
|
+
- title: "Culture"
|
|
80
|
+
description: "What we watch, wear, and argue about — and why it matters more than you think."
|
|
81
|
+
icon: "masks-theater"
|
|
82
|
+
href: "/blog/categories/culture"
|
|
83
|
+
- title: "Money"
|
|
84
|
+
description: "Markets, paychecks, and the economics hiding inside everyday decisions."
|
|
85
|
+
icon: "chart-line"
|
|
86
|
+
href: "/blog/categories/money"
|
|
87
|
+
|
|
88
|
+
# Stats Section — the masthead numbers
|
|
89
|
+
stats:
|
|
90
|
+
- number: "2M+"
|
|
91
|
+
label: "Monthly readers"
|
|
92
|
+
sublabel: "Across 120+ countries"
|
|
93
|
+
- number: "12k+"
|
|
94
|
+
label: "Stories published"
|
|
95
|
+
sublabel: "And counting"
|
|
96
|
+
- number: "5 min"
|
|
97
|
+
label: "Daily briefing"
|
|
98
|
+
sublabel: "Fully caught up"
|
|
99
|
+
- number: "0"
|
|
100
|
+
label: "Clickbait headlines"
|
|
101
|
+
sublabel: "We checked"
|
|
102
|
+
|
|
103
|
+
# CTA Section — the big-read band
|
|
104
|
+
cta:
|
|
105
|
+
superheadline:
|
|
106
|
+
icon: "bolt"
|
|
107
|
+
text: "The big read"
|
|
108
|
+
headline: "Don't just scroll the news."
|
|
109
|
+
headline_accent: "Understand it."
|
|
110
|
+
description: "Join the readers who start their day with {{ site.brand.name }} — reporting with teeth, context with heart, and zero filler."
|
|
111
|
+
primary_button:
|
|
112
|
+
text: "Start reading"
|
|
113
|
+
icon: "bolt"
|
|
114
|
+
href: "/blog"
|
|
115
|
+
secondary_button:
|
|
116
|
+
text: "Get the newsletter"
|
|
117
|
+
icon: "envelope"
|
|
118
|
+
href: "#signup"
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
{% comment %}
|
|
122
|
+
NEWSFLASH HOMEPAGE
|
|
123
|
+
A newspaper front page: a featured-story hero (publication pitch left, the
|
|
124
|
+
latest post as the framed cover story right), top-story tiles, "the latest"
|
|
125
|
+
as an editorial post feed (square art + kicker + headline + dek) with a
|
|
126
|
+
sticky rail sidebar (most-read + newsletter signup), "the rundown" as the
|
|
127
|
+
newsroom's numbered three-step playbook, coverage-desk cards (linked to
|
|
128
|
+
their category pages), a masthead numbers strip, "more to chew on" story
|
|
129
|
+
tiles, and a dark big-read CTA band. (Reader quotes live on the about page.)
|
|
130
|
+
Every section is rendered by this layout — no classy includes. The
|
|
131
|
+
frontmatter defaults are NEWS-genre copy — a theme's defaults are part of
|
|
132
|
+
its identity (see docs/themes.md "Frontmatter defaults are part of the
|
|
133
|
+
theme's identity"). Universal sections (hero, stats, cta, newsletter) keep
|
|
134
|
+
the shared key names; `latest`, `rundown`, `desks`, and `more_stories` are
|
|
135
|
+
newsflash-specific. Posts-driven sections disappear gracefully when
|
|
136
|
+
site.posts is empty.
|
|
137
|
+
{% endcomment %}
|
|
138
|
+
|
|
139
|
+
<!-- ============================================ -->
|
|
140
|
+
<!-- HERO — front page lead: pitch left, cover story right -->
|
|
141
|
+
<!-- ============================================ -->
|
|
142
|
+
<section class="section-hero pb-4">
|
|
143
|
+
<div class="container">
|
|
144
|
+
<div class="row align-items-center g-5">
|
|
145
|
+
<!-- Left: kicker + serif headline + dek + actions -->
|
|
146
|
+
<div class="col-lg-6" data-lazy="@class animation-slide-up">
|
|
147
|
+
{% iftruthy page.resolved.hero.tagline %}
|
|
148
|
+
<span class="kicker">{{ page.resolved.hero.tagline }}</span>
|
|
149
|
+
{% endiftruthy %}
|
|
150
|
+
<h1 class="hero-title my-3">
|
|
151
|
+
{{ page.resolved.hero.headline }}
|
|
152
|
+
{% iftruthy page.resolved.hero.headline_accent %}
|
|
153
|
+
<span class="text-accent">{{ page.resolved.hero.headline_accent }}</span>
|
|
154
|
+
{% endiftruthy %}
|
|
155
|
+
</h1>
|
|
156
|
+
{% iftruthy page.resolved.hero.description %}
|
|
157
|
+
<p class="lead mb-4" style="max-width: 34em;">{{ page.resolved.hero.description }}</p>
|
|
158
|
+
{% endiftruthy %}
|
|
159
|
+
<div class="d-flex flex-wrap gap-3">
|
|
160
|
+
{% iftruthy page.resolved.hero.primary_button %}
|
|
161
|
+
<a href="{{ page.resolved.hero.primary_button.href }}" class="btn btn-primary btn-lg">
|
|
162
|
+
{% uj_icon page.resolved.hero.primary_button.icon, "me-2" %}{{ page.resolved.hero.primary_button.text }}
|
|
163
|
+
</a>
|
|
164
|
+
{% endiftruthy %}
|
|
165
|
+
{% iftruthy page.resolved.hero.secondary_button %}
|
|
166
|
+
<a href="{{ page.resolved.hero.secondary_button.href }}" class="btn btn-outline-dark btn-lg">
|
|
167
|
+
{% uj_icon page.resolved.hero.secondary_button.icon, "me-2" %}{{ page.resolved.hero.secondary_button.text }}
|
|
168
|
+
</a>
|
|
169
|
+
{% endiftruthy %}
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<!-- Right: the cover story (latest post) — or a cover-art block pre-content -->
|
|
174
|
+
<div class="col-lg-6" data-lazy="@class animation-slide-up">
|
|
175
|
+
{% if site.posts.size > 0 %}
|
|
176
|
+
{% assign featured = site.posts.first %}
|
|
177
|
+
<a href="{{ site.url }}{{ featured.url }}" class="hero-art d-block position-relative text-decoration-none text-body">
|
|
178
|
+
<span class="badge bg-body-tertiary hero-art-chip">Featured</span>
|
|
179
|
+
<div class="art-frame shadow">
|
|
180
|
+
{%- uj_post featured.post.id, "image-tag", class="w-100" -%}
|
|
181
|
+
</div>
|
|
182
|
+
<div class="mt-3">
|
|
183
|
+
{% if featured.post.categories[0] %}
|
|
184
|
+
<span class="kicker mb-1">{{ featured.post.categories[0] | uj_title_case }}</span>
|
|
185
|
+
{% endif %}
|
|
186
|
+
<h2 class="h4 mb-1">{{ featured.post.title }}</h2>
|
|
187
|
+
<p class="small text-body-secondary mb-0">
|
|
188
|
+
<b class="text-body">{%- uj_member featured.post.author, "name" -%}</b>
|
|
189
|
+
· {{ featured.date | date: "%b %d, %Y" }}
|
|
190
|
+
· {% uj_readtime featured.content %} min read
|
|
191
|
+
</p>
|
|
192
|
+
</div>
|
|
193
|
+
</a>
|
|
194
|
+
{% else %}
|
|
195
|
+
<div class="hero-art position-relative">
|
|
196
|
+
<span class="badge bg-body-tertiary hero-art-chip">Featured</span>
|
|
197
|
+
<div class="art-frame shadow">
|
|
198
|
+
<div class="cover-art ratio ratio-4x3"></div>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
{% endif %}
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
</section>
|
|
206
|
+
|
|
207
|
+
<!-- ============================================ -->
|
|
208
|
+
<!-- TOP STORIES — three editorial tiles -->
|
|
209
|
+
<!-- ============================================ -->
|
|
210
|
+
{% if site.posts.size > 1 %}
|
|
211
|
+
<section class="pt-4">
|
|
212
|
+
<div class="container">
|
|
213
|
+
<div class="section-head" data-lazy="@class animation-slide-up">
|
|
214
|
+
<h2>Top stories</h2>
|
|
215
|
+
<span class="rule"></span>
|
|
216
|
+
<a href="{{ site.url }}/blog">View all {% uj_icon "arrow-right", "ms-1" %}</a>
|
|
217
|
+
</div>
|
|
218
|
+
<div class="row g-4">
|
|
219
|
+
{% for post in site.posts offset: 1 limit: 3 %}
|
|
220
|
+
<div class="col-md-4" data-lazy="@class animation-slide-up">
|
|
221
|
+
<a href="{{ site.url }}{{ post.url }}" class="story-card">
|
|
222
|
+
<div class="art-frame mb-3">
|
|
223
|
+
{%- uj_post post.post.id, "image-tag", class="w-100" -%}
|
|
224
|
+
</div>
|
|
225
|
+
{% if post.post.categories[0] %}
|
|
226
|
+
<span class="kicker mb-1">{{ post.post.categories[0] | uj_title_case }}</span>
|
|
227
|
+
{% endif %}
|
|
228
|
+
<h3 class="h5 my-2">{{ post.post.title }}</h3>
|
|
229
|
+
<p class="small text-body-secondary mb-0">
|
|
230
|
+
<b class="text-body">{%- uj_member post.post.author, "name" -%}</b>
|
|
231
|
+
· {% uj_readtime post.content %} min read
|
|
232
|
+
</p>
|
|
233
|
+
</a>
|
|
234
|
+
</div>
|
|
235
|
+
{% endfor %}
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
</section>
|
|
239
|
+
{% endif %}
|
|
240
|
+
|
|
241
|
+
<!-- ============================================ -->
|
|
242
|
+
<!-- THE LATEST — editorial post feed + sticky rail sidebar -->
|
|
243
|
+
<!-- (mirrors the front-page feed: square art, kicker, headline, dek, byline) -->
|
|
244
|
+
<!-- ============================================ -->
|
|
245
|
+
{% comment %}
|
|
246
|
+
Post slots are strictly deduplicated down the page: hero = post 1,
|
|
247
|
+
top stories = 2-4, this feed = 5-9, most-read rail = 10-14, "more to chew
|
|
248
|
+
on" = 15-17. Sections disappear gracefully when the site doesn't have
|
|
249
|
+
enough posts to fill their slice (only the ticker repeats the latest —
|
|
250
|
+
it's chrome, not content).
|
|
251
|
+
{% endcomment %}
|
|
252
|
+
{% if site.posts.size > 4 %}
|
|
253
|
+
<section class="section-feed">
|
|
254
|
+
<div class="container">
|
|
255
|
+
<div class="section-head" data-lazy="@class animation-slide-up">
|
|
256
|
+
{% iftruthy page.resolved.latest.superheadline.text %}
|
|
257
|
+
<h2>{{ page.resolved.latest.superheadline.text }}</h2>
|
|
258
|
+
{% endiftruthy %}
|
|
259
|
+
<span class="rule"></span>
|
|
260
|
+
{% iftruthy page.resolved.latest.view_all %}
|
|
261
|
+
<a href="{{ page.resolved.latest.view_all.href }}">{{ page.resolved.latest.view_all.text }} {% uj_icon "arrow-right", "ms-1" %}</a>
|
|
262
|
+
{% endiftruthy %}
|
|
263
|
+
</div>
|
|
264
|
+
|
|
265
|
+
<div class="row g-5">
|
|
266
|
+
<!-- The feed: posts 5-9 (hero + top stories show 1-4) -->
|
|
267
|
+
<div class="col-lg-7">
|
|
268
|
+
<div>
|
|
269
|
+
{% for post in site.posts offset: 4 limit: 5 %}
|
|
270
|
+
<a href="{{ site.url }}{{ post.url }}" class="feed-item" data-lazy="@class animation-slide-up">
|
|
271
|
+
<div class="art-frame">
|
|
272
|
+
{%- uj_post post.post.id, "image-tag", class="w-100" -%}
|
|
273
|
+
</div>
|
|
274
|
+
<div>
|
|
275
|
+
{% if post.post.categories[0] %}
|
|
276
|
+
<span class="kicker mb-1">{{ post.post.categories[0] | uj_title_case }}</span>
|
|
277
|
+
{% endif %}
|
|
278
|
+
<h3 class="h4 my-2">{{ post.post.title }}</h3>
|
|
279
|
+
{% iftruthy post.post.description %}
|
|
280
|
+
<p class="text-body-secondary mb-2">{{ post.post.description }}</p>
|
|
281
|
+
{% endiftruthy %}
|
|
282
|
+
<p class="small text-body-secondary mb-0">
|
|
283
|
+
<b class="text-body">{%- uj_member post.post.author, "name" -%}</b>
|
|
284
|
+
· {{ post.date | date: "%b %d, %Y" }}
|
|
285
|
+
· {% uj_readtime post.content %} min read
|
|
286
|
+
</p>
|
|
287
|
+
</div>
|
|
288
|
+
</a>
|
|
289
|
+
{% endfor %}
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
|
|
293
|
+
<!-- The rail -->
|
|
294
|
+
<aside class="col-lg-5 col-xl-4 ms-auto">
|
|
295
|
+
<div class="rail-stack d-flex flex-column gap-4">
|
|
296
|
+
{% comment %} Most read: posts 10-14 — the next slice after the feed (no duplicates) {% endcomment %}
|
|
297
|
+
{% if site.posts.size > 9 %}
|
|
298
|
+
<div class="card p-4" data-lazy="@class animation-slide-up">
|
|
299
|
+
<div class="rail-title">Most read</div>
|
|
300
|
+
<ol class="mostread list-unstyled mb-0">
|
|
301
|
+
{% for post in site.posts offset: 9 limit: 5 %}
|
|
302
|
+
<li>
|
|
303
|
+
<a href="{{ site.url }}{{ post.url }}">{{ post.post.title }}</a>
|
|
304
|
+
</li>
|
|
305
|
+
{% endfor %}
|
|
306
|
+
</ol>
|
|
307
|
+
</div>
|
|
308
|
+
{% endif %}
|
|
309
|
+
|
|
310
|
+
{% iftruthy page.resolved.newsletter %}
|
|
311
|
+
<div class="card bg-primary text-white p-4" data-lazy="@class animation-slide-up" id="signup">
|
|
312
|
+
<h3 class="h3 fst-italic mb-2">{{ page.resolved.newsletter.headline }}</h3>
|
|
313
|
+
<p class="small mb-3">{{ page.resolved.newsletter.subheadline }}</p>
|
|
314
|
+
<form class="d-flex gap-2 needs-validation" action="{{ site.url }}/email-subscription">
|
|
315
|
+
<label for="newsletter-email" class="visually-hidden">Email address</label>
|
|
316
|
+
<input type="email" name="email" id="newsletter-email" class="form-control" placeholder="{{ page.resolved.newsletter.form.placeholder }}" autocomplete="email" required>
|
|
317
|
+
<button type="submit" class="btn btn-dark">{{ page.resolved.newsletter.button.text }}</button>
|
|
318
|
+
</form>
|
|
319
|
+
{% iftruthy page.resolved.newsletter.disclaimer %}
|
|
320
|
+
<small class="d-block mt-2 opacity-75">{{ page.resolved.newsletter.disclaimer }}</small>
|
|
321
|
+
{% endiftruthy %}
|
|
322
|
+
</div>
|
|
323
|
+
{% endiftruthy %}
|
|
324
|
+
</div>
|
|
325
|
+
</aside>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
</section>
|
|
329
|
+
{% endif %}
|
|
330
|
+
|
|
331
|
+
<!-- ============================================ -->
|
|
332
|
+
<!-- THE RUNDOWN — the newsroom's numbered three-step playbook -->
|
|
333
|
+
<!-- ============================================ -->
|
|
334
|
+
<section class="section-rundown pt-0">
|
|
335
|
+
<div class="container">
|
|
336
|
+
<div class="section-head" data-lazy="@class animation-slide-up">
|
|
337
|
+
{% iftruthy page.resolved.rundown.superheadline.text %}
|
|
338
|
+
<h2>{{ page.resolved.rundown.superheadline.text }}</h2>
|
|
339
|
+
{% endiftruthy %}
|
|
340
|
+
<span class="rule"></span>
|
|
341
|
+
</div>
|
|
342
|
+
|
|
343
|
+
<header class="mb-4" data-lazy="@class animation-slide-up">
|
|
344
|
+
<h2 class="h1 mb-2">
|
|
345
|
+
{{ page.resolved.rundown.headline }}
|
|
346
|
+
{% iftruthy page.resolved.rundown.headline_accent %}
|
|
347
|
+
<span class="text-accent">{{ page.resolved.rundown.headline_accent }}</span>
|
|
348
|
+
{% endiftruthy %}
|
|
349
|
+
</h2>
|
|
350
|
+
{% iftruthy page.resolved.rundown.subheadline %}
|
|
351
|
+
<p class="lead mb-0">{{ page.resolved.rundown.subheadline }}</p>
|
|
352
|
+
{% endiftruthy %}
|
|
353
|
+
</header>
|
|
354
|
+
|
|
355
|
+
<div class="row">
|
|
356
|
+
<div class="col-lg-9">
|
|
357
|
+
{% for item in page.resolved.rundown.items %}
|
|
358
|
+
<article class="feed-item" data-lazy="@class animation-slide-up">
|
|
359
|
+
<div class="feed-num" aria-hidden="true">{{ forloop.index | prepend: '0' | slice: -2, 2 }}</div>
|
|
360
|
+
<div>
|
|
361
|
+
<h3 class="h4 mb-2">{{ item.title }}</h3>
|
|
362
|
+
<p class="text-body-secondary mb-0">{{ item.description }}</p>
|
|
363
|
+
</div>
|
|
364
|
+
</article>
|
|
365
|
+
{% endfor %}
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
</div>
|
|
369
|
+
</section>
|
|
370
|
+
|
|
371
|
+
<!-- ============================================ -->
|
|
372
|
+
<!-- THE DESKS — coverage cards in a paper well -->
|
|
373
|
+
<!-- ============================================ -->
|
|
374
|
+
<section class="bg-body-tertiary">
|
|
375
|
+
<div class="container">
|
|
376
|
+
<div class="section-head" data-lazy="@class animation-slide-up">
|
|
377
|
+
{% iftruthy page.resolved.desks.superheadline.text %}
|
|
378
|
+
<h2>{{ page.resolved.desks.superheadline.text }}</h2>
|
|
379
|
+
{% endiftruthy %}
|
|
380
|
+
<span class="rule"></span>
|
|
381
|
+
</div>
|
|
382
|
+
|
|
383
|
+
<header class="mb-5" data-lazy="@class animation-slide-up">
|
|
384
|
+
<h2 class="h1 mb-2">
|
|
385
|
+
{{ page.resolved.desks.headline }}
|
|
386
|
+
{% iftruthy page.resolved.desks.headline_accent %}
|
|
387
|
+
<span class="text-accent">{{ page.resolved.desks.headline_accent }}</span>
|
|
388
|
+
{% endiftruthy %}
|
|
389
|
+
</h2>
|
|
390
|
+
{% iftruthy page.resolved.desks.subheadline %}
|
|
391
|
+
<p class="lead mb-0">{{ page.resolved.desks.subheadline }}</p>
|
|
392
|
+
{% endiftruthy %}
|
|
393
|
+
</header>
|
|
394
|
+
|
|
395
|
+
<div class="row g-4">
|
|
396
|
+
{% for desk in page.resolved.desks.items %}
|
|
397
|
+
{% comment %} Each desk card links to its category page (href overrides the slugified title) {% endcomment %}
|
|
398
|
+
{% capture desk_href %}{% if desk.href %}{{ desk.href }}{% else %}/blog/categories/{{ desk.title | slugify }}{% endif %}{% endcapture %}
|
|
399
|
+
<div class="col-md-4" data-lazy="@class animation-slide-up">
|
|
400
|
+
<a href="{{ desk_href }}" class="card story-card h-100 p-4 text-decoration-none">
|
|
401
|
+
<span class="feature-icon d-inline-flex align-items-center justify-content-center rounded-circle text-bg-primary mb-3">
|
|
402
|
+
{% uj_icon desk.icon %}
|
|
403
|
+
</span>
|
|
404
|
+
<h3 class="h4 mb-2">{{ desk.title }}</h3>
|
|
405
|
+
<p class="text-body-secondary mb-0">{{ desk.description }}</p>
|
|
406
|
+
<span class="small fw-bold text-primary mt-3">Read the desk {% uj_icon "arrow-right", "ms-1" %}</span>
|
|
407
|
+
</a>
|
|
408
|
+
</div>
|
|
409
|
+
{% endfor %}
|
|
410
|
+
</div>
|
|
411
|
+
|
|
412
|
+
{% iftruthy page.resolved.desks.cta_button %}
|
|
413
|
+
<div class="text-center mt-5" data-lazy="@class animation-slide-up">
|
|
414
|
+
<a href="{{ page.resolved.desks.cta_button.href }}" class="btn btn-primary btn-lg">
|
|
415
|
+
{% uj_icon page.resolved.desks.cta_button.icon, "me-2" %}{{ page.resolved.desks.cta_button.text }}
|
|
416
|
+
</a>
|
|
417
|
+
</div>
|
|
418
|
+
{% endiftruthy %}
|
|
419
|
+
</div>
|
|
420
|
+
</section>
|
|
421
|
+
|
|
422
|
+
<!-- ============================================ -->
|
|
423
|
+
<!-- STATS — masthead numbers, stroked numerals -->
|
|
424
|
+
<!-- ============================================ -->
|
|
425
|
+
{% iftruthy page.resolved.stats %}
|
|
426
|
+
<section>
|
|
427
|
+
<div class="container">
|
|
428
|
+
<div class="section-head" data-lazy="@class animation-slide-up">
|
|
429
|
+
<h2>By the numbers</h2>
|
|
430
|
+
<span class="rule"></span>
|
|
431
|
+
</div>
|
|
432
|
+
<div class="row g-4 text-center">
|
|
433
|
+
{% for stat in page.resolved.stats %}
|
|
434
|
+
<div class="col-6 col-lg-3" data-lazy="@class animation-slide-up">
|
|
435
|
+
<div class="stat-num">{{ stat.number }}</div>
|
|
436
|
+
<div class="fw-bold">{{ stat.label }}</div>
|
|
437
|
+
{% iftruthy stat.sublabel %}
|
|
438
|
+
<div class="small text-body-secondary">{{ stat.sublabel }}</div>
|
|
439
|
+
{% endiftruthy %}
|
|
440
|
+
</div>
|
|
441
|
+
{% endfor %}
|
|
442
|
+
</div>
|
|
443
|
+
</div>
|
|
444
|
+
</section>
|
|
445
|
+
{% endiftruthy %}
|
|
446
|
+
|
|
447
|
+
<!-- ============================================ -->
|
|
448
|
+
<!-- MORE TO CHEW ON — extra story tiles before the big read -->
|
|
449
|
+
<!-- ============================================ -->
|
|
450
|
+
{% comment %} More to chew on: posts 15-17 — the slice after the most-read rail (no duplicates) {% endcomment %}
|
|
451
|
+
{% if site.posts.size > 14 %}
|
|
452
|
+
<section class="pt-0">
|
|
453
|
+
<div class="container">
|
|
454
|
+
<div class="section-head" data-lazy="@class animation-slide-up">
|
|
455
|
+
{% iftruthy page.resolved.more_stories.superheadline.text %}
|
|
456
|
+
<h2>{{ page.resolved.more_stories.superheadline.text }}</h2>
|
|
457
|
+
{% endiftruthy %}
|
|
458
|
+
<span class="rule"></span>
|
|
459
|
+
</div>
|
|
460
|
+
<div class="row g-4">
|
|
461
|
+
{% for post in site.posts offset: 14 limit: 3 %}
|
|
462
|
+
<div class="col-md-4" data-lazy="@class animation-slide-up">
|
|
463
|
+
<a href="{{ site.url }}{{ post.url }}" class="story-card">
|
|
464
|
+
<div class="art-frame mb-3">
|
|
465
|
+
{%- uj_post post.post.id, "image-tag", class="w-100" -%}
|
|
466
|
+
</div>
|
|
467
|
+
{% if post.post.categories[0] %}
|
|
468
|
+
<span class="kicker mb-1">{{ post.post.categories[0] | uj_title_case }}</span>
|
|
469
|
+
{% endif %}
|
|
470
|
+
<h3 class="h5 my-2">{{ post.post.title }}</h3>
|
|
471
|
+
<p class="small text-body-secondary mb-0">
|
|
472
|
+
<b class="text-body">{%- uj_member post.post.author, "name" -%}</b>
|
|
473
|
+
· {% uj_readtime post.content %} min read
|
|
474
|
+
</p>
|
|
475
|
+
</a>
|
|
476
|
+
</div>
|
|
477
|
+
{% endfor %}
|
|
478
|
+
</div>
|
|
479
|
+
</div>
|
|
480
|
+
</section>
|
|
481
|
+
{% endif %}
|
|
482
|
+
|
|
483
|
+
<!-- ============================================ -->
|
|
484
|
+
<!-- CTA — the dark big-read band -->
|
|
485
|
+
<!-- ============================================ -->
|
|
486
|
+
<section class="cta">
|
|
487
|
+
<div class="container">
|
|
488
|
+
<div class="cta-panel" data-lazy="@class animation-slide-up">
|
|
489
|
+
<div class="cta-rings" aria-hidden="true"></div>
|
|
490
|
+
<div class="position-relative">
|
|
491
|
+
{% iftruthy page.resolved.cta.superheadline.text %}
|
|
492
|
+
<span class="kicker mb-3">
|
|
493
|
+
{% uj_icon page.resolved.cta.superheadline.icon, "me-1" %}{{ page.resolved.cta.superheadline.text }}
|
|
494
|
+
</span>
|
|
495
|
+
{% endiftruthy %}
|
|
496
|
+
<h2 class="cta-title">
|
|
497
|
+
{{ page.resolved.cta.headline }}
|
|
498
|
+
{% iftruthy page.resolved.cta.headline_accent %}
|
|
499
|
+
<span class="text-accent">{{ page.resolved.cta.headline_accent }}</span>
|
|
500
|
+
{% endiftruthy %}
|
|
501
|
+
</h2>
|
|
502
|
+
{% iftruthy page.resolved.cta.description %}
|
|
503
|
+
<p class="cta-desc">{{ page.resolved.cta.description }}</p>
|
|
504
|
+
{% endiftruthy %}
|
|
505
|
+
<div class="d-flex flex-wrap gap-3">
|
|
506
|
+
{% iftruthy page.resolved.cta.primary_button %}
|
|
507
|
+
<a href="{{ page.resolved.cta.primary_button.href }}" class="btn btn-warning btn-lg">
|
|
508
|
+
{% uj_icon page.resolved.cta.primary_button.icon, "me-2" %}{{ page.resolved.cta.primary_button.text }}
|
|
509
|
+
</a>
|
|
510
|
+
{% endiftruthy %}
|
|
511
|
+
{% iftruthy page.resolved.cta.secondary_button %}
|
|
512
|
+
<a href="{{ page.resolved.cta.secondary_button.href }}" class="btn btn-outline-light btn-lg">
|
|
513
|
+
{% uj_icon page.resolved.cta.secondary_button.icon, "me-2" %}{{ page.resolved.cta.secondary_button.text }}
|
|
514
|
+
</a>
|
|
515
|
+
{% endiftruthy %}
|
|
516
|
+
</div>
|
|
517
|
+
</div>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
</section>
|
|
521
|
+
|
|
522
|
+
{{ content | uj_content_format }}
|