pandorga 1.6.0 → 1.6.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/DESIGN.md +1 -1
- data/_data/themes/shared.yml +3 -2
- data/_includes/content-runtime/60-fragments.html +1 -1
- data/_includes/theme/tailwind-theme-fonts.json.liquid +1 -1
- data/_includes/theme/theme-vars-block.liquid +2 -2
- data/_layouts/articles.html +19 -3
- data/_layouts/home.html +2 -3
- data/_layouts/shell.html +3 -3
- data/assets/css/ledger/home.css +3 -5
- data/assets/css/ledger/writing.css +4 -1
- data/assets/css/tailwind.css +1 -1
- data/lib/pandorga/hero_summary.rb +51 -0
- data/lib/pandorga/jekyll/plugins/hero_summary.rb +17 -0
- data/lib/pandorga/version.rb +1 -1
- data/scripts/tailwind/tailwind.config.js +2 -2
- data/scripts/test/test-examples-build.rb +20 -0
- data/scripts/test/test-hero-summary.rb +64 -0
- data/scripts/test/test-hydrate-reserve.rb +9 -3
- data/scripts/validate.sh +1 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a47af06e13cc8cf5264887f7ea3236ada5a5eb2f78b357c19861b30a6493ae55
|
|
4
|
+
data.tar.gz: 9e155005f14faf4a30d2095f8409d655d105b32528cda1fdec14c5a4488aea2a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: df895fc4b0d63410a5c620b73c7e842c045743e0de76514345176d55c3cbf771a2af251748976b8efee410f0cbd58e8f5c6ccf30ead7a832b3df4d1c16a35a9c
|
|
7
|
+
data.tar.gz: dc6321d8dc00e651fe8fcc2fdd61b8d78f45d730225d2f7100cd1e70fe9761c48c713fe9ca1d709b2c1cd8bb699bdd42df2f8b9bd6da4d05087c85a8bccd7d7b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.6.2] — 2026-10-10
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- The home hero summary is rendered from `content/pages/cv/summary.md` at
|
|
8
|
+
build time. It was painted from JSON, so the paragraph's LCP was almost
|
|
9
|
+
all render delay.
|
|
10
|
+
- The summary no longer reserves six empty lines. That box shifted the
|
|
11
|
+
call to action when the real paragraph arrived.
|
|
12
|
+
- The body face is requested before the ledger sheets. `font-display: swap`
|
|
13
|
+
stays. The fallback is Georgia, then serif, so the swap does not reflow
|
|
14
|
+
the summary from a sans.
|
|
15
|
+
|
|
16
|
+
No `pandorga:` config keys were added or renamed.
|
|
17
|
+
|
|
18
|
+
## [1.6.1] — 2026-10-10
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- The articles featured slot reserved 16rem whenever it was empty, so page 2
|
|
23
|
+
and later kept a blank band between the header rule and the filter. The
|
|
24
|
+
reserve now lasts only until the listing decides. A page with no specimen
|
|
25
|
+
collapses that slot.
|
|
26
|
+
|
|
27
|
+
No `pandorga:` config keys were added or renamed.
|
|
28
|
+
|
|
3
29
|
## [1.6.0] — 2026-10-10
|
|
4
30
|
|
|
5
31
|
### Added
|
data/DESIGN.md
CHANGED
|
@@ -159,7 +159,7 @@ typography:
|
|
|
159
159
|
title: "'Cinzel Decorative', serif"
|
|
160
160
|
subtitle: "'Newsreader', serif"
|
|
161
161
|
label: "'Marcellus SC', serif"
|
|
162
|
-
body: "'Newsreader',
|
|
162
|
+
body: "'Newsreader', Georgia, serif"
|
|
163
163
|
mono: "'Courier Prime', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace"
|
|
164
164
|
code: "'Courier Prime', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace"
|
|
165
165
|
rootFontSize: "110%"
|
data/_data/themes/shared.yml
CHANGED
|
@@ -13,8 +13,9 @@ fonts:
|
|
|
13
13
|
code: "Courier Prime"
|
|
14
14
|
cv_body: "Newsreader"
|
|
15
15
|
cv_body_weight: 400
|
|
16
|
-
#
|
|
17
|
-
|
|
16
|
+
# Fallback after the named face. Body is Newsreader, a serif. A sans
|
|
17
|
+
# fallback reflows the hero summary when the webfont swaps in.
|
|
18
|
+
body_fallback: "Georgia, serif"
|
|
18
19
|
subtitle_fallback: "serif"
|
|
19
20
|
title_fallback: "serif"
|
|
20
21
|
label_fallback: "serif"
|
|
@@ -219,7 +219,7 @@
|
|
|
219
219
|
function mountMarkdownFragment(relativePath, elementOrId, options) {
|
|
220
220
|
options = options || {};
|
|
221
221
|
var el = typeof elementOrId === 'string' ? document.getElementById(elementOrId) : elementOrId;
|
|
222
|
-
if (!el) return Promise.resolve();
|
|
222
|
+
if (!el || el.hasAttribute('data-content-static')) return Promise.resolve();
|
|
223
223
|
// A quiet slot keeps its reserved box. Writing "Loading..." into the
|
|
224
224
|
// hero summary makes that placeholder the LCP, then swaps it away.
|
|
225
225
|
var quiet = el.hasAttribute('data-content-quiet');
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
{% assign font_subtitle = sf.subtitle | default: "Lato" %}
|
|
4
4
|
{% assign font_label = sf.label | default: "Ysabeau SC" %}
|
|
5
5
|
{% assign font_body = sf.body | default: "Newsreader" %}
|
|
6
|
-
{"title":["var(--font-title)"],"subtitle":["var(--font-subtitle)","serif"],"label":["var(--font-label)","serif"],"body":["var(--font-body)","
|
|
6
|
+
{"title":["var(--font-title)"],"subtitle":["var(--font-subtitle)","serif"],"label":["var(--font-label)","serif"],"body":["var(--font-body)","Georgia","serif"],"headline":["var(--font-title)"],"editorial":["var(--font-title)"],"serif":["var(--font-title)"],"sans":["var(--font-body)","Georgia","serif"],"mono":["var(--font-mono)"],"code":["var(--font-code)"]}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
{% assign font_title_fallback = sf.title_fallback | default: "serif" %}
|
|
27
27
|
{% assign font_subtitle_fallback = sf.subtitle_fallback | default: "serif" %}
|
|
28
28
|
{% assign font_label_fallback = sf.label_fallback | default: "serif" %}
|
|
29
|
-
{% assign font_body_fallback = sf.body_fallback | default: "
|
|
29
|
+
{% assign font_body_fallback = sf.body_fallback | default: "Georgia, serif" %}
|
|
30
30
|
{% assign bg_secondary = tn.background_secondary | default: tn.surface_container_low | default: "#f5f5f5" %}
|
|
31
31
|
{% assign surface_value = tn.surface | default: "#ffffff" %}
|
|
32
32
|
{% assign surface_variant_value = tn.surface_variant | default: "#e2e2e2" %}
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
--font-subtitle: '{{ font_subtitle }}', {{ font_subtitle_fallback }};
|
|
37
37
|
--font-label: '{{ font_label }}', {{ font_label_fallback }};
|
|
38
38
|
--font-body: '{{ font_body }}', {{ font_body_fallback }};
|
|
39
|
-
--font-cv-body: '{{ font_cv_body }}',
|
|
39
|
+
--font-cv-body: '{{ font_cv_body }}', {{ font_body_fallback }};
|
|
40
40
|
--font-cv-body-weight: {{ font_cv_body_weight }};
|
|
41
41
|
--font-serif: '{{ font_title }}', {{ font_title_fallback }};
|
|
42
42
|
/* Content titles share the body face at 600 — Cinzel Decorative is
|
data/_layouts/articles.html
CHANGED
|
@@ -30,7 +30,16 @@ layout: shell
|
|
|
30
30
|
image column, and one that reserves space for a picture that does not
|
|
31
31
|
exist is worse than no panel at all.
|
|
32
32
|
{%- endcomment -%}
|
|
33
|
-
<div id="articles-lead"></div>
|
|
33
|
+
<div id="articles-lead" class="is-pending"></div>
|
|
34
|
+
<script>
|
|
35
|
+
(function () {
|
|
36
|
+
var page = parseInt(new URLSearchParams(window.location.search).get('page') || '1', 10);
|
|
37
|
+
var lead = document.getElementById('articles-lead');
|
|
38
|
+
if (!lead || !(page > 1)) return;
|
|
39
|
+
lead.classList.remove('is-pending');
|
|
40
|
+
lead.hidden = true;
|
|
41
|
+
})();
|
|
42
|
+
</script>
|
|
34
43
|
|
|
35
44
|
<div class="writing-body">
|
|
36
45
|
|
|
@@ -259,7 +268,11 @@ layout: shell
|
|
|
259
268
|
function renderListing(state) {
|
|
260
269
|
Array.from(grid.querySelectorAll('[data-dynamic-article]')).forEach(function (el) { el.remove(); });
|
|
261
270
|
if (emptyState) emptyState.remove();
|
|
262
|
-
if (leadRoot)
|
|
271
|
+
if (leadRoot) {
|
|
272
|
+
leadRoot.classList.remove('is-pending');
|
|
273
|
+
leadRoot.innerHTML = '';
|
|
274
|
+
leadRoot.hidden = true;
|
|
275
|
+
}
|
|
263
276
|
|
|
264
277
|
var visible = visibleArticles(state);
|
|
265
278
|
if (orderNote) orderNote.textContent = SORT_LABELS[state.sort] || SORT_LABELS.updated;
|
|
@@ -287,7 +300,10 @@ layout: shell
|
|
|
287
300
|
|
|
288
301
|
var totalPages = Math.max(1, Math.ceil(rest.length / perPage));
|
|
289
302
|
if (currentPage > totalPages) currentPage = totalPages;
|
|
290
|
-
if (currentPage === 1)
|
|
303
|
+
if (currentPage === 1) {
|
|
304
|
+
renderLead(featured);
|
|
305
|
+
if (leadRoot && leadRoot.childElementCount) leadRoot.hidden = false;
|
|
306
|
+
}
|
|
291
307
|
|
|
292
308
|
rest.slice((currentPage - 1) * perPage, currentPage * perPage).forEach(renderRow);
|
|
293
309
|
listing.renderPagination(controls, currentPage, totalPages);
|
data/_layouts/home.html
CHANGED
|
@@ -33,8 +33,7 @@ layout: shell
|
|
|
33
33
|
<h1 class="home-hero-title">
|
|
34
34
|
<span class="home-hero-given">{{ _hero_name.given }}</span>{%- if _hero_name.family != "" %} <span class="home-hero-family">{{ _hero_name.family }}</span>{%- endif %}
|
|
35
35
|
</h1>
|
|
36
|
-
|
|
37
|
-
data-content-fragment="cv/summary" data-content-quiet></div>
|
|
36
|
+
{% pandorga_hero_summary %}
|
|
38
37
|
<div class="home-hero-actions">
|
|
39
38
|
{%- if _cv_page -%}
|
|
40
39
|
<a class="ledger-cta ledger-cta--emphasis home-hero-cta" href="{{ _cv_page.url }}">
|
|
@@ -65,7 +64,7 @@ layout: shell
|
|
|
65
64
|
function paint(id, path) {
|
|
66
65
|
var el = document.getElementById(id);
|
|
67
66
|
var pending = pre[path];
|
|
68
|
-
if (!el || !pending || !runtime || !runtime.renderMarkdown) return;
|
|
67
|
+
if (!el || el.hasAttribute('data-content-static') || !pending || !runtime || !runtime.renderMarkdown) return;
|
|
69
68
|
pending.then(function (fragment) {
|
|
70
69
|
if (!fragment || el.getAttribute('data-content-painted') === '1') return;
|
|
71
70
|
var html = runtime.renderMarkdown(fragment.body_markdown || '');
|
data/_layouts/shell.html
CHANGED
|
@@ -58,6 +58,9 @@
|
|
|
58
58
|
<meta name="twitter:image" content="{{ og_image_url }}" />
|
|
59
59
|
<!-- Canonical URL -->
|
|
60
60
|
<link rel="canonical" href="{{ canonical_path | absolute_url }}" />
|
|
61
|
+
<link href="https://fonts.googleapis.com" rel="preconnect" />
|
|
62
|
+
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect" />
|
|
63
|
+
{% include theme/font-loader.html %}
|
|
61
64
|
{% include theme/critical-preload.html %}
|
|
62
65
|
<link rel="stylesheet" href="/assets/css/base.css" />
|
|
63
66
|
<link rel="stylesheet" href="/assets/css/global-link.css" />
|
|
@@ -107,9 +110,6 @@
|
|
|
107
110
|
{%- for _sheet in _ledger -%}
|
|
108
111
|
<link rel="stylesheet" href="/assets/css/ledger/{{ _sheet }}.css" />
|
|
109
112
|
{%- endfor -%}
|
|
110
|
-
<link href="https://fonts.googleapis.com" rel="preconnect" />
|
|
111
|
-
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect" />
|
|
112
|
-
{% include theme/font-loader.html %}
|
|
113
113
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap"
|
|
114
114
|
rel="stylesheet" />
|
|
115
115
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.2.3/css/flag-icons.min.css" />
|
data/assets/css/ledger/home.css
CHANGED
|
@@ -312,11 +312,9 @@
|
|
|
312
312
|
line-height: var(--leading-body);
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
-
/*
|
|
316
|
-
|
|
317
|
-
.
|
|
318
|
-
min-height: calc(var(--type-body) * var(--leading-body) * 6);
|
|
319
|
-
}
|
|
315
|
+
/* No empty min-height. A guessed line count shifts the call to action
|
|
316
|
+
when the summary is shorter or taller than the reserve. The paragraph
|
|
317
|
+
is in the HTML when content/pages/cv/summary.md exists. */
|
|
320
318
|
|
|
321
319
|
.home-hero-summary p {
|
|
322
320
|
margin: 0 0 var(--space-md);
|
|
@@ -297,7 +297,10 @@ html[data-theme="light"] .writing-index .writing-lead-media .ledger-poster {
|
|
|
297
297
|
background: var(--color-surface-card);
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
|
|
300
|
+
/* Hold the featured panel only until the listing decides. A standing
|
|
301
|
+
:empty rule kept this 16rem gap on page 2 and later, where no specimen
|
|
302
|
+
is drawn, between the header rule and the filter. */
|
|
303
|
+
#articles-lead.is-pending:empty {
|
|
301
304
|
min-height: 16rem;
|
|
302
305
|
margin-bottom: var(--space-xl);
|
|
303
306
|
}
|
data/assets/css/tailwind.css
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/* Compiled Tailwind utilities (3.4.17, forms plugin). Replaces the Play CDN.
|
|
2
2
|
Regenerate with scripts/tailwind/build.sh after adding a utility class. */
|
|
3
|
-
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-body),sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:var(--font-mono);font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],input:where(:not([type])),select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,input:where(:not([type])):focus,select:focus,textarea:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple],[size]:where(select:not([size="1"])){background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0'/%3E%3C/svg%3E")}@media (forced-colors:active) {[type=checkbox]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}@media (forced-colors:active) {[type=radio]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=radio]:checked:focus,[type=radio]:checked:hover{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media (forced-colors:active) {[type=checkbox]:indeterminate{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.left-0{left:0}.right-0{right:0}.top-0{top:0}.top-full{top:100%}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.col-span-full{grid-column:1/-1}.m-0{margin:0}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1\.5{margin-top:.375rem;margin-bottom:.375rem}.my-8{margin-top:2rem;margin-bottom:2rem}.my-\[1\.55em\]{margin-top:1.55em;margin-bottom:1.55em}.mb-10{margin-bottom:2.5rem}.mb-16{margin-bottom:4rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mb-\[0\.35rem\]{margin-bottom:.35rem}.ml-2{margin-left:.5rem}.mt-1{margin-top:.25rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.\!grid{display:grid!important}.grid{display:grid}.contents{display:contents}.\!hidden{display:none!important}.hidden{display:none}.h-12{height:3rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-\[12vw\]{height:12vw}.h-\[1px\]{height:1px}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.min-h-screen{min-height:100vh}.w-12{width:3rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[14rem\]{min-width:14rem}.min-w-\[3\.5rem\]{min-width:3.5rem}.min-w-\[9\.5rem\]{min-width:9.5rem}.max-w-7xl{max-width:80rem}.max-w-full{max-width:100%}.max-w-xs{max-width:20rem}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.resize{resize:both}.scroll-mt-28{scroll-margin-top:7rem}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.overflow-x-auto{overflow-x:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.rounded{border-radius:.125rem}.rounded-\[9999px\]{border-radius:9999px}.border{border-width:1px}.border-0{border-width:0}.border-t{border-top-width:1px}.border-gentle{border-color:var(--border-gentle)}.border-gentle-divider{border-color:var(--border-gentle-divider)}.border-gentle-subtle{border-color:var(--border-gentle-subtle)}.bg-background{background-color:var(--color-background)}.bg-surface{background-color:var(--color-surface)}.bg-surface-container-highest{background-color:var(--color-surface-container-highest)}.bg-surface-container-low{background-color:var(--color-surface-container-low)}.bg-transparent{background-color:transparent}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.pb-16{padding-bottom:4rem}.pb-3\.5{padding-bottom:.875rem}.pt-10{padding-top:2.5rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.align-top{vertical-align:top}.font-body{font-family:var(--font-body),sans-serif}.font-label{font-family:var(--font-label),serif}.font-mono{font-family:var(--font-mono)}.font-title{font-family:var(--font-title)}.text-5xl{font-size:3rem;line-height:1}.text-\[0\.8em\]{font-size:.8em}.text-\[0\.9em\]{font-size:.9em}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-light{font-weight:300}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.ordinal{--tw-ordinal:ordinal}.ordinal,.tabular-nums{font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.tabular-nums{--tw-numeric-spacing:tabular-nums}.leading-\[1\.55\]{line-height:1.55}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-widest{letter-spacing:.1em}.text-on-surface{color:var(--color-on-surface)}.text-on-surface-variant{color:var(--color-on-surface-variant)}.text-outline{color:var(--color-outline)}.text-primary{color:var(--color-primary)}.text-secondary{color:var(--color-secondary)}.text-tertiary{color:var(--color-tertiary)}.underline{text-decoration-line:underline}.no-underline{text-decoration-line:none}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.drop-shadow{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px rgba(0,0,0,.1)) drop-shadow(0 1px 1px rgba(0,0,0,.06))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.bg-outline-variant\/30{background-color:color-mix(in srgb,var(--color-outline-variant) 30%,transparent)}.border-tertiary\/40{border-color:color-mix(in srgb,var(--color-tertiary) 40%,transparent)}.hover\:border-primary:hover{border-color:var(--color-primary)}.hover\:border-tertiary:hover{border-color:var(--color-tertiary)}.hover\:bg-surface-container-low:hover{background-color:var(--color-surface-container-low)}.hover\:text-primary:hover{color:var(--color-primary)}.hover\:underline:hover{text-decoration-line:underline}.group:hover .group-hover\:bg-primary-container{background-color:var(--color-primary-container)}.group:hover .group-hover\:text-on-primary-container{color:var(--color-on-primary-container)}@media (min-width:640px){.sm\:gap-4{gap:1rem}.sm\:gap-5{gap:1.25rem}.sm\:px-8{padding-left:2rem;padding-right:2rem}}@media (min-width:768px){.md\:sticky{position:sticky}.md\:top-32{top:8rem}.md\:mb-12{margin-bottom:3rem}.md\:px-10{padding-left:2.5rem;padding-right:2.5rem}.md\:px-16{padding-left:4rem;padding-right:4rem}.md\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1024px){.lg\:sticky{position:sticky}.lg\:top-32{top:8rem}.lg\:gap-12{gap:3rem}}
|
|
3
|
+
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-body),Georgia,serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:var(--font-mono);font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],input:where(:not([type])),select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,input:where(:not([type])):focus,select:focus,textarea:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple],[size]:where(select:not([size="1"])){background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0'/%3E%3C/svg%3E")}@media (forced-colors:active) {[type=checkbox]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}@media (forced-colors:active) {[type=radio]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=radio]:checked:focus,[type=radio]:checked:hover{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media (forced-colors:active) {[type=checkbox]:indeterminate{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.left-0{left:0}.right-0{right:0}.top-0{top:0}.top-full{top:100%}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.col-span-full{grid-column:1/-1}.m-0{margin:0}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1\.5{margin-top:.375rem;margin-bottom:.375rem}.my-8{margin-top:2rem;margin-bottom:2rem}.my-\[1\.55em\]{margin-top:1.55em;margin-bottom:1.55em}.mb-10{margin-bottom:2.5rem}.mb-16{margin-bottom:4rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mb-\[0\.35rem\]{margin-bottom:.35rem}.ml-2{margin-left:.5rem}.mt-1{margin-top:.25rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.\!grid{display:grid!important}.grid{display:grid}.contents{display:contents}.\!hidden{display:none!important}.hidden{display:none}.h-12{height:3rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-\[12vw\]{height:12vw}.h-\[1px\]{height:1px}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.min-h-screen{min-height:100vh}.w-12{width:3rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[14rem\]{min-width:14rem}.min-w-\[3\.5rem\]{min-width:3.5rem}.min-w-\[9\.5rem\]{min-width:9.5rem}.max-w-7xl{max-width:80rem}.max-w-full{max-width:100%}.max-w-xs{max-width:20rem}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.resize{resize:both}.scroll-mt-28{scroll-margin-top:7rem}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.overflow-x-auto{overflow-x:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.rounded{border-radius:.125rem}.rounded-\[9999px\]{border-radius:9999px}.border{border-width:1px}.border-0{border-width:0}.border-t{border-top-width:1px}.border-gentle{border-color:var(--border-gentle)}.border-gentle-divider{border-color:var(--border-gentle-divider)}.border-gentle-subtle{border-color:var(--border-gentle-subtle)}.bg-background{background-color:var(--color-background)}.bg-surface{background-color:var(--color-surface)}.bg-surface-container-highest{background-color:var(--color-surface-container-highest)}.bg-surface-container-low{background-color:var(--color-surface-container-low)}.bg-transparent{background-color:transparent}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.pb-16{padding-bottom:4rem}.pb-3\.5{padding-bottom:.875rem}.pt-10{padding-top:2.5rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.align-top{vertical-align:top}.font-body{font-family:var(--font-body),Georgia,serif}.font-label{font-family:var(--font-label),serif}.font-mono{font-family:var(--font-mono)}.font-title{font-family:var(--font-title)}.text-5xl{font-size:3rem;line-height:1}.text-\[0\.8em\]{font-size:.8em}.text-\[0\.9em\]{font-size:.9em}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-light{font-weight:300}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.ordinal{--tw-ordinal:ordinal}.ordinal,.tabular-nums{font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.tabular-nums{--tw-numeric-spacing:tabular-nums}.leading-\[1\.55\]{line-height:1.55}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-widest{letter-spacing:.1em}.text-on-surface{color:var(--color-on-surface)}.text-on-surface-variant{color:var(--color-on-surface-variant)}.text-outline{color:var(--color-outline)}.text-primary{color:var(--color-primary)}.text-secondary{color:var(--color-secondary)}.text-tertiary{color:var(--color-tertiary)}.underline{text-decoration-line:underline}.no-underline{text-decoration-line:none}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.drop-shadow{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px rgba(0,0,0,.1)) drop-shadow(0 1px 1px rgba(0,0,0,.06))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.bg-outline-variant\/30{background-color:color-mix(in srgb,var(--color-outline-variant) 30%,transparent)}.border-tertiary\/40{border-color:color-mix(in srgb,var(--color-tertiary) 40%,transparent)}.hover\:border-primary:hover{border-color:var(--color-primary)}.hover\:border-tertiary:hover{border-color:var(--color-tertiary)}.hover\:bg-surface-container-low:hover{background-color:var(--color-surface-container-low)}.hover\:text-primary:hover{color:var(--color-primary)}.hover\:underline:hover{text-decoration-line:underline}.group:hover .group-hover\:bg-primary-container{background-color:var(--color-primary-container)}.group:hover .group-hover\:text-on-primary-container{color:var(--color-on-primary-container)}@media (min-width:640px){.sm\:gap-4{gap:1rem}.sm\:gap-5{gap:1.25rem}.sm\:px-8{padding-left:2rem;padding-right:2rem}}@media (min-width:768px){.md\:sticky{position:sticky}.md\:top-32{top:8rem}.md\:mb-12{margin-bottom:3rem}.md\:px-10{padding-left:2.5rem;padding-right:2.5rem}.md\:px-16{padding-left:4rem;padding-right:4rem}.md\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1024px){.lg\:sticky{position:sticky}.lg\:top-32{top:8rem}.lg\:gap-12{gap:3rem}}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Home hero summary from content/pages/cv/summary.md.
|
|
4
|
+
# That paragraph is the LCP element. Leaving it empty until JSON arrives
|
|
5
|
+
# makes most of LCP render delay, and a guessed empty box shifts the
|
|
6
|
+
# call to action when the real text replaces it.
|
|
7
|
+
# Refs: PLT-AC-23
|
|
8
|
+
module Pandorga
|
|
9
|
+
module HeroSummary
|
|
10
|
+
RELATIVE = "content/pages/cv/summary.md"
|
|
11
|
+
FALLBACK = '<div id="home-cv-summary" class="home-hero-summary font-body" ' \
|
|
12
|
+
'data-content-fragment="cv/summary" data-content-quiet></div>'
|
|
13
|
+
|
|
14
|
+
module_function
|
|
15
|
+
|
|
16
|
+
def markdown(source_root)
|
|
17
|
+
root = File.expand_path(source_root.to_s)
|
|
18
|
+
path = File.expand_path(RELATIVE, root)
|
|
19
|
+
prefix = root.end_with?(File::SEPARATOR) ? root : root + File::SEPARATOR
|
|
20
|
+
return "" unless path.start_with?(prefix)
|
|
21
|
+
return "" unless File.file?(path)
|
|
22
|
+
|
|
23
|
+
strip_front_matter(File.read(path, encoding: "UTF-8")).strip
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def strip_front_matter(text)
|
|
27
|
+
text = text.to_s.sub(/\A\xEF\xBB\xBF/, "")
|
|
28
|
+
return text unless text.start_with?("---\n")
|
|
29
|
+
|
|
30
|
+
parts = text.split(/^---\s*$\n?/, 3)
|
|
31
|
+
return text unless parts.length == 3
|
|
32
|
+
|
|
33
|
+
parts[2]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def html_for(site)
|
|
37
|
+
text = markdown(site.source)
|
|
38
|
+
return "" if text.empty?
|
|
39
|
+
|
|
40
|
+
converter = site.find_converter_instance(::Jekyll::Converters::Markdown)
|
|
41
|
+
converter.convert(text).to_s.strip
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def element(html)
|
|
45
|
+
body = html.to_s.strip
|
|
46
|
+
return FALLBACK if body.empty?
|
|
47
|
+
|
|
48
|
+
%(<div id="home-cv-summary" class="home-hero-summary font-body" data-content-static>#{body}</div>)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "jekyll"
|
|
4
|
+
require_relative "../../hero_summary"
|
|
5
|
+
|
|
6
|
+
module Pandorga
|
|
7
|
+
# Emits the hero summary element. HTML is raw so the paragraph is in the
|
|
8
|
+
# first response when the markdown file exists.
|
|
9
|
+
class HeroSummaryTag < Liquid::Tag
|
|
10
|
+
def render(context)
|
|
11
|
+
site = context.registers[:site]
|
|
12
|
+
HeroSummary.element(HeroSummary.html_for(site))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Liquid::Template.register_tag("pandorga_hero_summary", Pandorga::HeroSummaryTag)
|
data/lib/pandorga/version.rb
CHANGED
|
@@ -81,11 +81,11 @@ module.exports = {
|
|
|
81
81
|
title: ["var(--font-title)"],
|
|
82
82
|
subtitle: ["var(--font-subtitle)", "serif"],
|
|
83
83
|
label: ["var(--font-label)", "serif"],
|
|
84
|
-
body: ["var(--font-body)", "
|
|
84
|
+
body: ["var(--font-body)", "Georgia", "serif"],
|
|
85
85
|
headline: ["var(--font-title)"],
|
|
86
86
|
editorial: ["var(--font-title)"],
|
|
87
87
|
serif: ["var(--font-title)"],
|
|
88
|
-
sans: ["var(--font-body)", "
|
|
88
|
+
sans: ["var(--font-body)", "Georgia", "serif"],
|
|
89
89
|
mono: ["var(--font-mono)"],
|
|
90
90
|
code: ["var(--font-code)"],
|
|
91
91
|
},
|
|
@@ -55,6 +55,26 @@ end
|
|
|
55
55
|
warn "FAIL test-examples-build: #{name} home layout missing"
|
|
56
56
|
exit 1
|
|
57
57
|
end
|
|
58
|
+
static_summary = 'id="home-cv-summary" class="home-hero-summary font-body" data-content-static>'
|
|
59
|
+
if name == "full"
|
|
60
|
+
unless html.include?(static_summary) && html.include?("Ada Example designs publishing frames")
|
|
61
|
+
warn "FAIL test-examples-build: full home summary is not static HTML"
|
|
62
|
+
exit 1
|
|
63
|
+
end
|
|
64
|
+
if html.include?('data-content-fragment="cv/summary"')
|
|
65
|
+
warn "FAIL test-examples-build: full home still hydrates the summary"
|
|
66
|
+
exit 1
|
|
67
|
+
end
|
|
68
|
+
else
|
|
69
|
+
unless html.include?('id="home-cv-summary" class="home-hero-summary font-body" data-content-fragment="cv/summary" data-content-quiet')
|
|
70
|
+
warn "FAIL test-examples-build: minimal home dropped the summary fallback"
|
|
71
|
+
exit 1
|
|
72
|
+
end
|
|
73
|
+
if html.include?(static_summary)
|
|
74
|
+
warn "FAIL test-examples-build: minimal home inlined a missing summary"
|
|
75
|
+
exit 1
|
|
76
|
+
end
|
|
77
|
+
end
|
|
58
78
|
origin = name == "full" ? "https://example.org" : "https://example.com"
|
|
59
79
|
sitemap = example.join("_site/sitemap.xml").read
|
|
60
80
|
robots = example.join("_site/robots.txt").read
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Hero summary is HTML at build time. The empty box and the sans fallback
|
|
5
|
+
# were the home CLS. PLT-AC-23.
|
|
6
|
+
|
|
7
|
+
require "pathname"
|
|
8
|
+
require "tmpdir"
|
|
9
|
+
require "fileutils"
|
|
10
|
+
|
|
11
|
+
ROOT = Pathname.new(__dir__).join("..", "..").expand_path
|
|
12
|
+
|
|
13
|
+
def fail!(message)
|
|
14
|
+
warn "FAIL test-hero-summary: #{message}"
|
|
15
|
+
exit 1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
require_relative "../../lib/pandorga/hero_summary"
|
|
19
|
+
|
|
20
|
+
Dir.mktmpdir("hero-summary") do |dir|
|
|
21
|
+
fail!("missing file must not invent a summary") unless Pandorga::HeroSummary.markdown(dir) == ""
|
|
22
|
+
|
|
23
|
+
path = File.join(dir, "content/pages/cv")
|
|
24
|
+
FileUtils.mkdir_p(path)
|
|
25
|
+
File.write(File.join(path, "summary.md"), "Ada Example designs publishing frames.\n")
|
|
26
|
+
plain = Pandorga::HeroSummary.markdown(dir)
|
|
27
|
+
fail!("plain summary was #{plain.inspect}") unless plain == "Ada Example designs publishing frames."
|
|
28
|
+
|
|
29
|
+
File.write(File.join(path, "summary.md"), "---\ntitle: Summary\n---\nAfter the matter.\n")
|
|
30
|
+
mattered = Pandorga::HeroSummary.markdown(dir)
|
|
31
|
+
fail!("front matter leaked: #{mattered.inspect}") unless mattered == "After the matter."
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
fallback = Pandorga::HeroSummary.element("")
|
|
35
|
+
fail!("missing summary must stay a quiet fragment") unless fallback.include?('data-content-fragment="cv/summary" data-content-quiet')
|
|
36
|
+
fail!("missing summary must not claim to be static") if fallback.include?("data-content-static")
|
|
37
|
+
|
|
38
|
+
static = Pandorga::HeroSummary.element("<p>Ada Example designs publishing frames.</p>")
|
|
39
|
+
fail!("static summary dropped the sentence") unless static.include?("Ada Example designs publishing frames.")
|
|
40
|
+
fail!("static summary is not marked static") unless static.include?("data-content-static")
|
|
41
|
+
fail!("static summary still hydrates") if static.include?("data-content-fragment")
|
|
42
|
+
|
|
43
|
+
home = ROOT.join("_layouts/home.html").read
|
|
44
|
+
home_css = ROOT.join("assets/css/ledger/home.css").read
|
|
45
|
+
shell = ROOT.join("_layouts/shell.html").read
|
|
46
|
+
fonts = ROOT.join("_includes/theme/font-loader.html").read
|
|
47
|
+
shared = ROOT.join("_data/themes/shared.yml").read
|
|
48
|
+
fragments = ROOT.join("_includes/content-runtime/60-fragments.html").read
|
|
49
|
+
|
|
50
|
+
fail!("home does not render the summary tag") unless home.include?("pandorga_hero_summary")
|
|
51
|
+
fail!("early paint replaces a static summary") unless home.include?("el.hasAttribute('data-content-static')")
|
|
52
|
+
fail!("summary keeps a guessed empty box") if home_css.include?(".home-hero-summary:empty")
|
|
53
|
+
fail!("a static summary can still be rewritten") unless fragments.include?("data-content-static")
|
|
54
|
+
fail!("font stylesheet dropped display=swap") unless fonts.include?("&display=swap")
|
|
55
|
+
|
|
56
|
+
font_at = shell.index("theme/font-loader.html")
|
|
57
|
+
base_at = shell.index('href="/assets/css/base.css"')
|
|
58
|
+
preconnect_at = shell.index("fonts.googleapis.com")
|
|
59
|
+
fail!("font loader missing") unless font_at
|
|
60
|
+
fail!("body face is requested after the ledger sheets") unless font_at < base_at
|
|
61
|
+
fail!("font host is not preconnected before the stylesheet") unless preconnect_at && preconnect_at < font_at
|
|
62
|
+
fail!("body fallback is still a sans") unless shared.include?('body_fallback: "Georgia, serif"')
|
|
63
|
+
|
|
64
|
+
puts "PASS test-hero-summary"
|
|
@@ -35,17 +35,23 @@ fail!("loadJson ignores the preload cache") unless fragments.include?("window.__
|
|
|
35
35
|
fail!("quiet fragments still write Loading...") unless fragments.include?("data-content-quiet")
|
|
36
36
|
fail!("a painted fragment is written twice") unless fragments.include?("data-content-painted")
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
summary_tag = ROOT.join("lib/pandorga/hero_summary.rb").read
|
|
39
|
+
fail!("hero summary fallback is not quiet") unless summary_tag.include?('data-content-fragment="cv/summary" data-content-quiet')
|
|
39
40
|
fail!("hero subtitle is not quiet") unless home.include?('data-content-fragment="home/subtitle" data-content-quiet')
|
|
40
41
|
fail!("hero does not paint the summary early") unless home.include?("paint('home-cv-summary'")
|
|
42
|
+
fail!("early paint replaces a static summary") unless home.include?("el.hasAttribute('data-content-static')")
|
|
41
43
|
fail!("hero subtitle size left --type-body") unless home_css.include?("font-size: var(--type-body);")
|
|
42
44
|
tagline = home_css[/\.home-hero-tagline \{[^}]*\}/m]
|
|
43
45
|
fail!("tagline rule missing") unless tagline
|
|
44
46
|
fail!("tagline is not body size") unless tagline.include?("font-size: var(--type-body);")
|
|
45
|
-
fail!("hero summary
|
|
47
|
+
fail!("hero summary keeps a guessed empty box") if home_css.include?(".home-hero-summary:empty")
|
|
46
48
|
|
|
47
49
|
fail!("articles listing has no row reserve") unless articles.include?("writing-reserve-row")
|
|
48
|
-
fail!("articles lead has no reserved box") unless writing_css.include?("#articles-lead:empty")
|
|
50
|
+
fail!("articles lead has no reserved box") unless writing_css.include?("#articles-lead.is-pending:empty")
|
|
51
|
+
fail!("articles lead reserve stays after the listing decides") if writing_css.match?(/^#articles-lead:empty/m)
|
|
52
|
+
fail!("articles lead is not pending until the listing decides") unless articles.include?('id="articles-lead" class="is-pending"')
|
|
53
|
+
fail!("page 2 does not drop the lead reserve before paint") unless articles.include?("!(page > 1)")
|
|
54
|
+
fail!("listing never clears the lead reserve") unless articles.include?("leadRoot.classList.remove('is-pending')")
|
|
49
55
|
fail!("CV experience has no reserve") unless cv.include?('id="cv-experience-list"') && cv.include?("data-content-reserve")
|
|
50
56
|
fail!("CV summary still ships Loading...") if cv.include?("Loading...")
|
|
51
57
|
fail!("showLoadingState collapses a reserve") unless listing.include?("data-content-reserve")
|
data/scripts/validate.sh
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pandorga
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.6.
|
|
4
|
+
version: 1.6.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Pandorga contributors
|
|
@@ -272,6 +272,7 @@ files:
|
|
|
272
272
|
- lib/pandorga/commands/serve.rb
|
|
273
273
|
- lib/pandorga/commands/studio_schema.rb
|
|
274
274
|
- lib/pandorga/discovery.rb
|
|
275
|
+
- lib/pandorga/hero_summary.rb
|
|
275
276
|
- lib/pandorga/jekyll.rb
|
|
276
277
|
- lib/pandorga/jekyll/generator.rb
|
|
277
278
|
- lib/pandorga/jekyll/plugins/bibliography_artifact.rb
|
|
@@ -289,6 +290,7 @@ files:
|
|
|
289
290
|
- lib/pandorga/jekyll/plugins/force_utf8_encoding.rb
|
|
290
291
|
- lib/pandorga/jekyll/plugins/git_chronology.rb
|
|
291
292
|
- lib/pandorga/jekyll/plugins/git_metadata.rb
|
|
293
|
+
- lib/pandorga/jekyll/plugins/hero_summary.rb
|
|
292
294
|
- lib/pandorga/jekyll/plugins/identity_name.rb
|
|
293
295
|
- lib/pandorga/jekyll/plugins/job_sections.rb
|
|
294
296
|
- lib/pandorga/jekyll/plugins/lib/content_validators.rb
|
|
@@ -404,6 +406,7 @@ files:
|
|
|
404
406
|
- scripts/test/test-hero-name.rb
|
|
405
407
|
- scripts/test/test-hero-portraits.mjs
|
|
406
408
|
- scripts/test/test-hero-portraits.rb
|
|
409
|
+
- scripts/test/test-hero-summary.rb
|
|
407
410
|
- scripts/test/test-home-band-art.rb
|
|
408
411
|
- scripts/test/test-hydrate-reserve.rb
|
|
409
412
|
- scripts/test/test-install-functions.rb
|