@port60/template-kit 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -3
- package/src/vendor/contract/v1/behaviours.json +4 -4
- package/src/vendor/contract/v1/content-model.json +372 -76
- package/src/vendor/contract/v1/context.json +60 -3
- package/src/vendor/contract/v1/islands.json +55 -1
- package/src/vendor/contract/v1/manifest.schema.json +132 -25
- package/src/vendor/contract/v1/sections.json +18 -6
- package/src/vendor/validator/behaviors-runtime.js +1 -1
- package/src/vendor/validator/platform-base.css +317 -0
- package/src/vendor/validator/preview.mjs +11 -0
- package/src/vendor/validator/validate.mjs +15 -1
- package/starter/manifest.json +7 -2
- package/starter/sections/homeHero.liquid +9 -8
|
@@ -25,6 +25,50 @@
|
|
|
25
25
|
],
|
|
26
26
|
"description": "Navigation: items (curated main or platform-derived), footer, derived, the flat-era nav shape, re-addressed."
|
|
27
27
|
},
|
|
28
|
+
{
|
|
29
|
+
"path": "site.focus",
|
|
30
|
+
"availableIn": [
|
|
31
|
+
"section",
|
|
32
|
+
"layout"
|
|
33
|
+
],
|
|
34
|
+
"description": "What leads on the site: 'donate' (default) or 'volunteer'. The charity's one switch (docs/volunteering.md 'Site focus'); everything below follows from it."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"path": "site.actions",
|
|
38
|
+
"availableIn": [
|
|
39
|
+
"section",
|
|
40
|
+
"layout"
|
|
41
|
+
],
|
|
42
|
+
"description": "The two resolved actions: primary { kind, label, href } is the focus (the widget in the hero); secondary is the other action (the header button). Both always exist."
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"path": "section.primary",
|
|
46
|
+
"availableIn": [
|
|
47
|
+
"section"
|
|
48
|
+
],
|
|
49
|
+
"description": "homeHero only: the leading action { kind, label, href }, the same as site.actions.primary. Render it as a widget with {% island 'primary_action' %} when section.actionStyle is 'widget'."
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"path": "section.secondary",
|
|
53
|
+
"availableIn": [
|
|
54
|
+
"section"
|
|
55
|
+
],
|
|
56
|
+
"description": "homeHero only: the other action { kind, label, href }, the same as site.actions.secondary; the header button carries it."
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"path": "section.action",
|
|
60
|
+
"availableIn": [
|
|
61
|
+
"section"
|
|
62
|
+
],
|
|
63
|
+
"description": "homeHero only: the hero's own button { kind, label, href }: the action whose widget is NOT on the page (donation widget present, the button is Volunteer; volunteer widget present, the button is Donate), or the leading action when actionStyle is 'button'. Render it as the first hero button unless the author set primaryLabel / primaryHref; the second button stays the author's story link."
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"path": "section.actionStyle",
|
|
67
|
+
"availableIn": [
|
|
68
|
+
"section"
|
|
69
|
+
],
|
|
70
|
+
"description": "homeHero only: 'widget' (the leading action's widget sits in the hero) or 'button' (copy only, the primary button is the way in). The old givingStyle value is kept as an alias ('form' = 'widget')."
|
|
71
|
+
},
|
|
28
72
|
{
|
|
29
73
|
"path": "site.socials",
|
|
30
74
|
"availableIn": [
|
|
@@ -208,7 +252,7 @@
|
|
|
208
252
|
"availableIn": [
|
|
209
253
|
"layout"
|
|
210
254
|
],
|
|
211
|
-
"description": "Platform key (facebook, instagram, x,
|
|
255
|
+
"description": "Platform key (facebook, instagram, x, \u2026).",
|
|
212
256
|
"deprecated": true
|
|
213
257
|
},
|
|
214
258
|
{
|
|
@@ -1029,7 +1073,7 @@
|
|
|
1029
1073
|
},
|
|
1030
1074
|
{
|
|
1031
1075
|
"code": "ar",
|
|
1032
|
-
"label": "
|
|
1076
|
+
"label": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629",
|
|
1033
1077
|
"direction": "rtl"
|
|
1034
1078
|
}
|
|
1035
1079
|
]
|
|
@@ -1914,7 +1958,7 @@
|
|
|
1914
1958
|
},
|
|
1915
1959
|
{
|
|
1916
1960
|
"code": "ar",
|
|
1917
|
-
"label": "
|
|
1961
|
+
"label": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629",
|
|
1918
1962
|
"direction": "rtl"
|
|
1919
1963
|
}
|
|
1920
1964
|
]
|
|
@@ -2382,6 +2426,19 @@
|
|
|
2382
2426
|
}
|
|
2383
2427
|
],
|
|
2384
2428
|
"about": []
|
|
2429
|
+
},
|
|
2430
|
+
"focus": "donate",
|
|
2431
|
+
"actions": {
|
|
2432
|
+
"primary": {
|
|
2433
|
+
"kind": "donate",
|
|
2434
|
+
"label": "Donate",
|
|
2435
|
+
"href": "/donate"
|
|
2436
|
+
},
|
|
2437
|
+
"secondary": {
|
|
2438
|
+
"kind": "volunteer",
|
|
2439
|
+
"label": "Volunteer",
|
|
2440
|
+
"href": "/volunteer"
|
|
2441
|
+
}
|
|
2385
2442
|
}
|
|
2386
2443
|
}
|
|
2387
2444
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"description": "The full donation flow for the tenant's quick-give cause: suggested amounts, custom amount, donor details, Gift Aid opt-in, payment. All payment/compliance behaviour is platform-owned.",
|
|
9
9
|
"params": [],
|
|
10
10
|
"stylingApi": [
|
|
11
|
+
".action-card",
|
|
11
12
|
".donate-card",
|
|
12
13
|
".donate-head",
|
|
13
14
|
".donate-sub",
|
|
@@ -34,7 +35,11 @@
|
|
|
34
35
|
".nav-account",
|
|
35
36
|
".nav-account-toggle",
|
|
36
37
|
".nav-account-menu",
|
|
37
|
-
".p60-mark"
|
|
38
|
+
".p60-mark",
|
|
39
|
+
".nav-p60-signin-label",
|
|
40
|
+
".nav-account-name",
|
|
41
|
+
".nav-account-caret",
|
|
42
|
+
".nav-account-icon"
|
|
38
43
|
]
|
|
39
44
|
},
|
|
40
45
|
{
|
|
@@ -239,6 +244,55 @@
|
|
|
239
244
|
".impact-map-card-cta",
|
|
240
245
|
".impact-map-empty"
|
|
241
246
|
]
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"name": "volunteer_signup",
|
|
250
|
+
"label": "Volunteer sign-up",
|
|
251
|
+
"status": "preview",
|
|
252
|
+
"description": "The volunteer sign-up flow: what to help with (general, then the events and campaigns that need people), when (only when the opportunity runs in shifts), a few details, then confirmation by a charity-branded email that also signs the volunteer in. Shares the donation widget's card vocabulary so a themed donate card themes this too; the vol-* classes cover what is specific to asking for help.",
|
|
253
|
+
"params": [],
|
|
254
|
+
"stylingApi": [
|
|
255
|
+
".donate-card",
|
|
256
|
+
".action-card",
|
|
257
|
+
".vol-body",
|
|
258
|
+
".volunteer-card",
|
|
259
|
+
".vol-card",
|
|
260
|
+
".vol-chosen",
|
|
261
|
+
".vol-search",
|
|
262
|
+
".vol-list",
|
|
263
|
+
".vol-group",
|
|
264
|
+
".vol-group-label",
|
|
265
|
+
".vol-option",
|
|
266
|
+
".vol-option-main",
|
|
267
|
+
".vol-option-summary",
|
|
268
|
+
".vol-option-meta",
|
|
269
|
+
".vol-needed",
|
|
270
|
+
".vol-shift-count",
|
|
271
|
+
".vol-form",
|
|
272
|
+
".vol-availability",
|
|
273
|
+
".vol-chips",
|
|
274
|
+
".vol-chip",
|
|
275
|
+
".vol-confirm",
|
|
276
|
+
".vol-optional",
|
|
277
|
+
".vol-why",
|
|
278
|
+
".vol-extra",
|
|
279
|
+
".vol-summary",
|
|
280
|
+
".vol-signed-in",
|
|
281
|
+
".vol-summary-needed",
|
|
282
|
+
".vol-field-error"
|
|
283
|
+
]
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"name": "primary_action",
|
|
287
|
+
"label": "Primary action",
|
|
288
|
+
"status": "available",
|
|
289
|
+
"description": "The composite for the site focus: mounts the donation widget or the volunteer sign-up according to what the charity chose to lead with (site.focus), so a template places one static island and the choice moves without a variable name. Both widgets wear .action-card; .donate-card and .volunteer-card carry kind-specific treatment. A template that wants a different layout per kind branches on section.primary.kind and places donation_widget or volunteer_signup directly.",
|
|
290
|
+
"params": [],
|
|
291
|
+
"stylingApi": [
|
|
292
|
+
".action-card",
|
|
293
|
+
".donate-card",
|
|
294
|
+
".volunteer-card"
|
|
295
|
+
]
|
|
242
296
|
}
|
|
243
297
|
]
|
|
244
298
|
}
|
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
"title": "Port60 template manifest (contract v1)",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": false,
|
|
7
|
-
"required": [
|
|
7
|
+
"required": [
|
|
8
|
+
"name",
|
|
9
|
+
"version",
|
|
10
|
+
"format",
|
|
11
|
+
"supports"
|
|
12
|
+
],
|
|
8
13
|
"properties": {
|
|
9
14
|
"name": {
|
|
10
15
|
"type": "string",
|
|
@@ -18,11 +23,20 @@
|
|
|
18
23
|
},
|
|
19
24
|
"format": {
|
|
20
25
|
"type": "string",
|
|
21
|
-
"enum": [
|
|
26
|
+
"enum": [
|
|
27
|
+
"port60-liquid@1"
|
|
28
|
+
],
|
|
22
29
|
"description": "The dialect/contract major this template is written against."
|
|
23
30
|
},
|
|
24
|
-
"label": {
|
|
25
|
-
|
|
31
|
+
"label": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"maxLength": 60,
|
|
34
|
+
"description": "Human-readable name shown in pickers."
|
|
35
|
+
},
|
|
36
|
+
"description": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"maxLength": 300
|
|
39
|
+
},
|
|
26
40
|
"requiresCapabilities": {
|
|
27
41
|
"type": "array",
|
|
28
42
|
"items": {
|
|
@@ -52,7 +66,15 @@
|
|
|
52
66
|
"type": "array",
|
|
53
67
|
"items": {
|
|
54
68
|
"type": "string",
|
|
55
|
-
"enum": [
|
|
69
|
+
"enum": [
|
|
70
|
+
"general",
|
|
71
|
+
"mosque",
|
|
72
|
+
"church",
|
|
73
|
+
"appeal-charity",
|
|
74
|
+
"pta",
|
|
75
|
+
"community",
|
|
76
|
+
"training"
|
|
77
|
+
]
|
|
56
78
|
},
|
|
57
79
|
"uniqueItems": true,
|
|
58
80
|
"default": [],
|
|
@@ -66,25 +88,38 @@
|
|
|
66
88
|
"supports": {
|
|
67
89
|
"type": "object",
|
|
68
90
|
"additionalProperties": false,
|
|
69
|
-
"required": [
|
|
91
|
+
"required": [
|
|
92
|
+
"pages",
|
|
93
|
+
"sections"
|
|
94
|
+
],
|
|
70
95
|
"properties": {
|
|
71
96
|
"pages": {
|
|
72
97
|
"type": "array",
|
|
73
|
-
"items": {
|
|
98
|
+
"items": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"enum": [
|
|
101
|
+
"home",
|
|
102
|
+
"about"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
74
105
|
"minItems": 1,
|
|
75
106
|
"uniqueItems": true,
|
|
76
107
|
"description": "Section based page bodies this template renders from sections/{type}.liquid. Contract v1 supports home and about. This is independent of layout chrome and route-specific pageTemplates."
|
|
77
108
|
},
|
|
78
109
|
"sections": {
|
|
79
110
|
"type": "array",
|
|
80
|
-
"items": {
|
|
111
|
+
"items": {
|
|
112
|
+
"type": "string"
|
|
113
|
+
},
|
|
81
114
|
"minItems": 1,
|
|
82
115
|
"uniqueItems": true,
|
|
83
116
|
"description": "Section types this template ships renderers for (sections/{type}.liquid). Unsupported types are omitted at render, never an error."
|
|
84
117
|
},
|
|
85
118
|
"islands": {
|
|
86
119
|
"type": "array",
|
|
87
|
-
"items": {
|
|
120
|
+
"items": {
|
|
121
|
+
"type": "string"
|
|
122
|
+
},
|
|
88
123
|
"uniqueItems": true,
|
|
89
124
|
"default": [],
|
|
90
125
|
"description": "Islands this template places. Every {% island %} name must be listed here AND exist in the platform island registry."
|
|
@@ -96,7 +131,15 @@
|
|
|
96
131
|
},
|
|
97
132
|
"pageTemplates": {
|
|
98
133
|
"type": "array",
|
|
99
|
-
"items": {
|
|
134
|
+
"items": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"enum": [
|
|
137
|
+
"events",
|
|
138
|
+
"course",
|
|
139
|
+
"articles",
|
|
140
|
+
"article"
|
|
141
|
+
]
|
|
142
|
+
},
|
|
100
143
|
"uniqueItems": true,
|
|
101
144
|
"default": [],
|
|
102
145
|
"description": "Route-specific data views rendered from pages/{page}.liquid with documented context. Events and articles own listings; course and article own detail presentation. Event transactions, course enrolment, article engagement, comments, identity and consent stay platform-owned islands. Requires supports.layout; without an entry the platform body renders inside the template chrome."
|
|
@@ -115,10 +158,34 @@
|
|
|
115
158
|
"type": "array",
|
|
116
159
|
"items": {
|
|
117
160
|
"type": "string",
|
|
118
|
-
"enum": [
|
|
161
|
+
"enum": [
|
|
162
|
+
"reveal",
|
|
163
|
+
"counter",
|
|
164
|
+
"progress",
|
|
165
|
+
"countdown",
|
|
166
|
+
"accordion",
|
|
167
|
+
"carousel",
|
|
168
|
+
"stickyHeader",
|
|
169
|
+
"stickyCta",
|
|
170
|
+
"lightbox",
|
|
171
|
+
"tabs",
|
|
172
|
+
"nav"
|
|
173
|
+
]
|
|
119
174
|
},
|
|
120
175
|
"uniqueItems": true,
|
|
121
176
|
"description": "Engine-attached behaviours this template's markup opts into via data-p60-* attributes (see the behaviour catalogue). Templates never ship JavaScript; declaring here is what makes the engine wire the markup, and the validator proves declaration and usage agree in both directions."
|
|
177
|
+
},
|
|
178
|
+
"focus": {
|
|
179
|
+
"type": "array",
|
|
180
|
+
"uniqueItems": true,
|
|
181
|
+
"items": {
|
|
182
|
+
"type": "string",
|
|
183
|
+
"enum": [
|
|
184
|
+
"donate",
|
|
185
|
+
"volunteer"
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
"description": "The site-focus kinds this template can LEAD with (docs/volunteering.md). Declaring 'volunteer' means the home hero places the composite primary_action island (or branches on section.primary.kind), so the volunteer sign-up can take the widget slot; the picker marks templates that cannot lead with volunteering. Templates that predate the setting keep rendering the donation widget, since donate is the default."
|
|
122
189
|
}
|
|
123
190
|
}
|
|
124
191
|
},
|
|
@@ -130,7 +197,10 @@
|
|
|
130
197
|
"hero": {
|
|
131
198
|
"type": "object",
|
|
132
199
|
"additionalProperties": false,
|
|
133
|
-
"required": [
|
|
200
|
+
"required": [
|
|
201
|
+
"idealAspect",
|
|
202
|
+
"minWidth"
|
|
203
|
+
],
|
|
134
204
|
"properties": {
|
|
135
205
|
"idealAspect": {
|
|
136
206
|
"type": "string",
|
|
@@ -166,7 +236,10 @@
|
|
|
166
236
|
"items": {
|
|
167
237
|
"type": "object",
|
|
168
238
|
"additionalProperties": false,
|
|
169
|
-
"required": [
|
|
239
|
+
"required": [
|
|
240
|
+
"name",
|
|
241
|
+
"values"
|
|
242
|
+
],
|
|
170
243
|
"properties": {
|
|
171
244
|
"name": {
|
|
172
245
|
"type": "string",
|
|
@@ -176,14 +249,18 @@
|
|
|
176
249
|
"values": {
|
|
177
250
|
"type": "object",
|
|
178
251
|
"minProperties": 1,
|
|
179
|
-
"propertyNames": {
|
|
180
|
-
|
|
181
|
-
|
|
252
|
+
"propertyNames": {
|
|
253
|
+
"pattern": "^[a-zA-Z][a-zA-Z0-9]{0,39}$"
|
|
254
|
+
},
|
|
255
|
+
"additionalProperties": {
|
|
256
|
+
"type": "string"
|
|
257
|
+
},
|
|
258
|
+
"description": "Knob key \u2192 value. Every key must be a declared settings knob; select values must be listed options; font values must be catalogue families."
|
|
182
259
|
}
|
|
183
260
|
}
|
|
184
261
|
},
|
|
185
262
|
"default": [],
|
|
186
|
-
"description": "One-click LOOKS: author-named bundles of knob values (scheme + fonts + width
|
|
263
|
+
"description": "One-click LOOKS: author-named bundles of knob values (scheme + fonts + width\u2026) applied together. Everything remains individually adjustable afterwards."
|
|
187
264
|
},
|
|
188
265
|
"settings": {
|
|
189
266
|
"type": "object",
|
|
@@ -194,21 +271,51 @@
|
|
|
194
271
|
"items": {
|
|
195
272
|
"type": "object",
|
|
196
273
|
"additionalProperties": false,
|
|
197
|
-
"required": [
|
|
274
|
+
"required": [
|
|
275
|
+
"key",
|
|
276
|
+
"kind",
|
|
277
|
+
"label"
|
|
278
|
+
],
|
|
198
279
|
"properties": {
|
|
199
|
-
"key": {
|
|
200
|
-
|
|
201
|
-
|
|
280
|
+
"key": {
|
|
281
|
+
"type": "string",
|
|
282
|
+
"pattern": "^[a-zA-Z][a-zA-Z0-9]{0,39}$"
|
|
283
|
+
},
|
|
284
|
+
"kind": {
|
|
285
|
+
"type": "string",
|
|
286
|
+
"enum": [
|
|
287
|
+
"color",
|
|
288
|
+
"select",
|
|
289
|
+
"toggle",
|
|
290
|
+
"font"
|
|
291
|
+
]
|
|
292
|
+
},
|
|
293
|
+
"label": {
|
|
294
|
+
"type": "string",
|
|
295
|
+
"maxLength": 60
|
|
296
|
+
},
|
|
202
297
|
"default": {},
|
|
203
|
-
"options": {
|
|
298
|
+
"options": {
|
|
299
|
+
"type": "array",
|
|
300
|
+
"items": {
|
|
301
|
+
"type": "string"
|
|
302
|
+
}
|
|
303
|
+
},
|
|
204
304
|
"group": {
|
|
205
305
|
"type": "string",
|
|
206
|
-
"enum": [
|
|
207
|
-
|
|
306
|
+
"enum": [
|
|
307
|
+
"typography",
|
|
308
|
+
"looks"
|
|
309
|
+
],
|
|
310
|
+
"description": "Where the admin surfaces this knob: 'typography' \u2192 the Typography section beside the font slots; 'looks' \u2192 the Looks section with the one-click bundles (colour schemes and accent dials belong there, and ungrouped color knobs plus a knob keyed 'scheme' default there anyway); other ungrouped knobs render under Template options."
|
|
208
311
|
},
|
|
209
312
|
"weights": {
|
|
210
313
|
"type": "array",
|
|
211
|
-
"items": {
|
|
314
|
+
"items": {
|
|
315
|
+
"type": "integer",
|
|
316
|
+
"minimum": 100,
|
|
317
|
+
"maximum": 1000
|
|
318
|
+
},
|
|
212
319
|
"uniqueItems": true,
|
|
213
320
|
"description": "FONT knobs only: the weights this template's typographic system uses for the slot. The host requests these for the tenant's chosen family (clamped to the family's real weights). The tenant picks the FAMILY; weights, sizes and tracking stay template-owned."
|
|
214
321
|
}
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
"name": "images",
|
|
238
238
|
"kind": "items",
|
|
239
239
|
"required": false,
|
|
240
|
-
"description": "Hero photographs (0
|
|
240
|
+
"description": "Hero photographs (0\u20136, uploaded through the platform pipeline). One = a main image; several = rotation material, a template with supports.heroImagery renders at least the first and MAY place the hero_carousel island (or a CSS scroll strip) for the rest. Like every field: absent means the template's designed no-photo state, never a placeholder.",
|
|
241
241
|
"itemFields": [
|
|
242
242
|
{
|
|
243
243
|
"name": "imageUrl",
|
|
@@ -360,16 +360,16 @@
|
|
|
360
360
|
"items": [
|
|
361
361
|
{
|
|
362
362
|
"imageUrl": "p60fixture:impact/parcel",
|
|
363
|
-
"title": "
|
|
363
|
+
"title": "\u00a310 \u00b7 A family food parcel",
|
|
364
364
|
"description": "Three days of meals, toiletries and a bag of fresh produce from the garden."
|
|
365
365
|
},
|
|
366
366
|
{
|
|
367
|
-
"icon": "
|
|
368
|
-
"title": "
|
|
367
|
+
"icon": "\ud83d\udd25",
|
|
368
|
+
"title": "\u00a325 \u00b7 A warm week",
|
|
369
369
|
"description": "Heating top-ups for a household choosing between eating and heating."
|
|
370
370
|
},
|
|
371
371
|
{
|
|
372
|
-
"title": "
|
|
372
|
+
"title": "\u00a350 \u00b7 A month of youth club",
|
|
373
373
|
"description": "Coaching, kit and hot food for a young person, four evenings a week."
|
|
374
374
|
}
|
|
375
375
|
]
|
|
@@ -513,7 +513,7 @@
|
|
|
513
513
|
"pages": [
|
|
514
514
|
"home"
|
|
515
515
|
],
|
|
516
|
-
"description": "Big headline numbers, the at-a-glance impact band. Values are author-entered text (write them exactly as they should read).",
|
|
516
|
+
"description": "Big headline numbers, the at-a-glance impact band. Values are author-entered text (write them exactly as they should read), or, per item, a live figure the platform counts (`source`).",
|
|
517
517
|
"fields": [
|
|
518
518
|
{
|
|
519
519
|
"name": "eyebrow",
|
|
@@ -544,6 +544,18 @@
|
|
|
544
544
|
"kind": "text",
|
|
545
545
|
"required": true,
|
|
546
546
|
"description": "What it counts (e.g. meals served)."
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
"name": "source",
|
|
550
|
+
"kind": "select",
|
|
551
|
+
"required": false,
|
|
552
|
+
"options": [
|
|
553
|
+
"volunteers.active",
|
|
554
|
+
"volunteers.hoursThisYear",
|
|
555
|
+
"volunteers.opportunitiesOpen",
|
|
556
|
+
"volunteers.needed"
|
|
557
|
+
],
|
|
558
|
+
"description": "A figure the platform counts rather than the author types (volunteers who helped in the last twelve months, hours logged this year, opportunities open now, volunteers still needed). When set, `value` is replaced at render with the live count, formatted for the site's locale; templates render `value` exactly as before."
|
|
547
559
|
}
|
|
548
560
|
]
|
|
549
561
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// GENERATED by scripts/build-behaviors-runtime.mjs — do not edit by hand.
|
|
2
|
-
"use strict";var p60Behaviors=(()=>{var M=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var q=(n,s)=>{for(var e in s)M(n,e,{get:s[e],enumerable:!0})},I=(n,s,e,o)=>{if(s&&typeof s=="object"||typeof s=="function")for(let t of N(s))!P.call(n,t)&&t!==e&&M(n,t,{get:()=>s[t],enumerable:!(o=H(s,t))||o.enumerable});return n};var C=n=>I(M({},"__esModule",{value:!0}),n);var W={};q(W,{initBehaviors:()=>G});var L=()=>window.matchMedia("(prefers-reduced-motion: reduce)").matches;function y(n,s){let e=`data-p60-bound-${s}`;return n.hasAttribute(e)?!0:(n.setAttribute(e,""),!1)}function T(n,s){if(n.length===0)return;if(L()||!("IntersectionObserver"in window)){n.forEach(s);return}let e=new IntersectionObserver(o=>{for(let t of o)t.isIntersecting&&(e.unobserve(t.target),s(t.target))},{rootMargin:"0px 0px -10% 0px",threshold:.15});n.forEach(o=>e.observe(o))}function O(n){let s=Array.from(n.querySelectorAll("[data-p60-reveal-group]")).filter(o=>!y(o,"reveal-group"));for(let o of s)Array.from(o.children).forEach((t,a)=>{t.style.setProperty("--p60-reveal-index",String(a)),t.classList.add("p60-reveal-child")});T(s,o=>o.classList.add("is-revealed"));let e=Array.from(n.querySelectorAll("[data-p60-reveal]")).filter(o=>!y(o,"reveal"));T(e,o=>o.classList.add("is-revealed"))}function D(n){let s=Array.from(n.querySelectorAll("[data-p60-count]")).filter(e=>!y(e,"count"));T(s,e=>{e.classList.add("is-revealed");let o=Number.parseInt(e.getAttribute("data-p60-count")??"",10);if(!Number.isFinite(o)||L())return;let t=Math.min(Number.parseInt(e.getAttribute("data-p60-count-duration")??"1200",10)||1200,4e3),a=new Intl.NumberFormat(document.documentElement.lang||void 0),c=performance.now(),r=i=>{let d=Math.min((i-c)/t,1),l=1-Math.pow(1-d,3);e.textContent=a.format(Math.round(o*l)),d<1&&requestAnimationFrame(r)};requestAnimationFrame(r)})}function B(n){let s=Array.from(n.querySelectorAll("[data-p60-progress]")).filter(e=>!y(e,"progress"));if(!L()){for(let e of s){let o=e.style.width||getComputedStyle(e).width;e.style.transition="none",e.style.width="0px",e.offsetWidth,e.style.transition="width 1.1s cubic-bezier(0.22, 1, 0.36, 1)",e.dataset.p60ProgressTarget=o}T(s,e=>{e.classList.add("is-revealed"),e.style.width=e.dataset.p60ProgressTarget??""})}}function F(n){let s=Array.from(n.querySelectorAll("[data-p60-countdown]")).filter(e=>!y(e,"countdown"));for(let e of s){let o=Date.parse(e.getAttribute("data-p60-until")??"");if(!Number.isFinite(o))continue;let t=e.getAttribute("data-p60-countdown")||"dhm",a=t==="dhms",c=()=>{let i=o-Date.now();if(i<=0){e.classList.add("is-elapsed");let u=e.getAttribute("data-p60-elapsed-text");u&&(e.textContent=u),window.clearInterval(r);return}let d=Math.floor(i/1e3),l=Math.floor(d/86400),f=Math.floor(d%86400/3600),g=Math.floor(d%3600/60),m=d%60,v=[];t.includes("d")&&l>0&&v.push(`${l}d`),v.push(`${f}h`,`${g}m`),a&&v.push(`${m}s`),e.textContent=v.join(" ")},r=window.setInterval(c,a?1e3:15e3);c()}}function _(n){let s=Array.from(n.querySelectorAll("[data-p60-accordion]")).filter(e=>!y(e,"accordion"));for(let e of s){let o=e.getAttribute("data-p60-accordion")!=="multi",t=Array.from(e.querySelectorAll("details"));for(let a of t){a.addEventListener("toggle",()=>{if(a.classList.toggle("is-open",a.open),a.open&&o)for(let i of t)i!==a&&i.open&&(i.open=!1)}),a.open&&a.classList.add("is-open");let r=a.querySelector("summary")?.nextElementSibling;r&&!L()&&a.addEventListener("toggle",()=>{if(!a.open)return;let i=r.scrollHeight;r.style.overflow="hidden",r.animate([{height:"0px",opacity:"0"},{height:`${i}px`,opacity:"1"}],{duration:260,easing:"ease-out"}).addEventListener("finish",()=>{r.style.overflow=""})})}}}function R(n){let s=Array.from(n.querySelectorAll("[data-p60-carousel]")).filter(e=>!y(e,"carousel"));for(let e of s){let o=Array.from(e.querySelectorAll("[data-p60-slide]"));if(o.length<2)continue;let t=Math.max(0,o.findIndex(u=>u.classList.contains("is-active"))),a=!1,c=[],r=document.createElement("nav");r.className="p60-carousel-dots",r.setAttribute("aria-label","Slides"),o.forEach((u,b)=>{let p=document.createElement("button");p.type="button",p.className="p60-carousel-dot",p.setAttribute("aria-label",`Go to slide ${b+1}`),p.addEventListener("click",()=>i(b,!0)),c.push(p),r.appendChild(p)}),e.appendChild(r),e.setAttribute("aria-roledescription","carousel"),e.hasAttribute("tabindex")||e.setAttribute("tabindex","0");let i=(u,b=!1)=>{t=(u+o.length)%o.length,o.forEach((p,h)=>{p.classList.toggle("is-active",h===t),h===t?(p.removeAttribute("aria-hidden"),p.removeAttribute("inert")):(p.setAttribute("aria-hidden","true"),p.setAttribute("inert",""))}),c.forEach((p,h)=>{p.classList.toggle("p60-carousel-dot--active",h===t),p.setAttribute("aria-current",h===t?"true":"false")}),e.style.setProperty("--p60-carousel-index",String(t)),b&&v()};e.querySelectorAll("[data-p60-carousel-prev]").forEach(u=>u.addEventListener("click",()=>i(t-1,!0))),e.querySelectorAll("[data-p60-carousel-next]").forEach(u=>u.addEventListener("click",()=>i(t+1,!0))),e.addEventListener("keydown",u=>{u.key==="ArrowLeft"&&i(t-1,!0),u.key==="ArrowRight"&&i(t+1,!0)});let d=0,l=0;e.addEventListener("pointerdown",u=>{d=u.clientX,l=u.clientY}),e.addEventListener("pointerup",u=>{let b=u.clientX-d,p=u.clientY-l;Math.abs(b)>40&&Math.abs(b)>Math.abs(p)&&i(t+(b<0?1:-1),!0)}),e.addEventListener("mouseenter",()=>{a=!0}),e.addEventListener("mouseleave",()=>{a=!1}),e.addEventListener("focusin",()=>{a=!0}),e.addEventListener("focusout",()=>{a=!1});let f,g=e.getAttribute("data-p60-carousel")==="auto"&&!L(),m=Math.max(Number.parseInt(e.getAttribute("data-p60-interval")??"6000",10)||6e3,3e3),v=()=>{f!==void 0&&window.clearInterval(f),g&&(f=window.setInterval(()=>{!a&&!document.hidden&&i(t+1)},m))};i(t),v()}}function Y(n){let s=Array.from(n.querySelectorAll("[data-p60-sticky-header]")).filter(e=>!y(e,"sticky-header"));for(let e of s){let o=e.getAttribute("data-p60-sticky-header")==="auto-hide",t=window.scrollY,a=!1,c=()=>{let r=window.scrollY;e.classList.toggle("is-condensed",r>24),o&&(r>160&&r>t?e.classList.add("is-hidden"):e.classList.remove("is-hidden")),t=r,a=!1};window.addEventListener("scroll",()=>{a||(a=!0,requestAnimationFrame(c))},{passive:!0}),c()}}function $(n){let s=Array.from(n.querySelectorAll("[data-p60-sticky-cta]")).filter(e=>!y(e,"sticky-cta"));for(let e of s){let o=Number.parseInt(e.getAttribute("data-p60-sticky-cta")??"480",10)||480,t=!1,a=()=>{e.classList.toggle("is-stuck",window.scrollY>o),t=!1};window.addEventListener("scroll",()=>{t||(t=!0,requestAnimationFrame(a))},{passive:!0}),a()}}function K(n){let s=Array.from(n.querySelectorAll("[data-p60-lightbox]")).filter(e=>!y(e,"lightbox"));for(let e of s){let o=Array.from(e.querySelectorAll("a[data-p60-lightbox-item]"));if(o.length===0)continue;let t=null,a=0,c=null,r=()=>{t?.remove(),t=null,e.classList.remove("is-open"),document.removeEventListener("keydown",d),c?.focus()},i=f=>{a=(f+o.length)%o.length;let g=o[a];if(!t)return;let m=t.querySelector(".p60-lightbox-img"),v=t.querySelector(".p60-lightbox-caption");m&&(m.src=g.href);let u=g.getAttribute("data-p60-caption")??g.querySelector("img")?.alt??"";v&&(v.textContent=u),m&&(m.alt=u)},d=f=>{if(f.key==="Escape"&&r(),f.key==="ArrowLeft"&&i(a-1),f.key==="ArrowRight"&&i(a+1),f.key==="Tab"&&t){let g=Array.from(t.querySelectorAll("button")),m=g.indexOf(document.activeElement),v=f.shiftKey?m<=0?g.length-1:m-1:m>=g.length-1?0:m+1;g[v]?.focus(),f.preventDefault()}},l=(f,g)=>{c=g,t=document.createElement("div"),t.className="p60-lightbox",t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),L()&&(t.style.transition="none"),t.innerHTML='<figure><img class="p60-lightbox-img" alt=""><figcaption class="p60-lightbox-caption"></figcaption></figure>';let m=(u,b,p)=>{let h=document.createElement("button");return h.type="button",h.className=u,h.setAttribute("aria-label",b),h.addEventListener("click",p),t.appendChild(h),h};o.length>1&&(m("p60-lightbox-prev","Previous image",()=>i(a-1)),m("p60-lightbox-next","Next image",()=>i(a+1)));let v=m("p60-lightbox-close","Close",r);t.addEventListener("click",u=>{u.target===t&&r()}),document.body.appendChild(t),e.classList.add("is-open"),document.addEventListener("keydown",d),i(f),v.focus()};o.forEach((f,g)=>f.addEventListener("click",m=>{m.preventDefault(),l(g,f)}))}}function V(n){let s=Array.from(n.querySelectorAll("[data-p60-tabs]")).filter(e=>!y(e,"tabs"));for(let e of s){let o=Array.from(e.querySelectorAll("[data-p60-tab]")),t=Array.from(e.querySelectorAll("[data-p60-panel]"));if(o.length===0||t.length===0)continue;let a=r=>t.find(i=>i.getAttribute("data-p60-panel")===r.getAttribute("data-p60-tab"));o[0].closest("[data-p60-tabs] > *")?.setAttribute("role","tablist");let c=(r,i=!1)=>{for(let d of o){let l=d===r;d.classList.toggle("is-active",l),d.setAttribute("aria-selected",l?"true":"false"),d.setAttribute("tabindex",l?"0":"-1")}for(let d of t){let l=d===a(r);d.classList.toggle("is-active",l),d.hidden=!l}i&&r.focus()};o.forEach((r,i)=>{r.setAttribute("role","tab"),r.addEventListener("click",d=>{d.preventDefault(),c(r)}),r.addEventListener("keydown",d=>{let l=d.key;l==="ArrowLeft"&&c(o[(i-1+o.length)%o.length],!0),l==="ArrowRight"&&c(o[(i+1)%o.length],!0),l==="Home"&&c(o[0],!0),l==="End"&&c(o[o.length-1],!0)})}),t.forEach(r=>r.setAttribute("role","tabpanel")),c(o.find(r=>r.classList.contains("is-active"))??o[0])}}var X=60,j=280,x=()=>window.matchMedia("(hover: hover)").matches,z='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',A=new Set,k=!1;function S(n){n.openTimer!==null&&(window.clearTimeout(n.openTimer),n.openTimer=null),n.closeTimer!==null&&(window.clearTimeout(n.closeTimer),n.closeTimer=null)}function E(n,s=!1){S(n);for(let e of Array.from(A))e!==n&&n.item.contains(e.item)&&E(e);n.item.classList.remove("is-open"),n.toggle.setAttribute("aria-expanded","false"),n.openedBy=null,A.delete(n),s&&n.toggle.focus()}function w(n,s){S(n);for(let e of Array.from(A))e!==n&&e.nav===n.nav&&!e.item.contains(n.item)&&E(e);n.item.classList.add("is-open"),n.toggle.setAttribute("aria-expanded","true"),n.openedBy=s,A.add(n)}function U(n){for(let e of Array.from(n.querySelectorAll("[data-p60-nav]"))){let o=Array.from(e.querySelectorAll("[data-p60-nav-item]")).filter(t=>t.closest("[data-p60-nav]")===e&&!y(t,"nav-item"));for(let t of o){let a=l=>l.closest("[data-p60-nav-item]")===t,c=Array.from(t.querySelectorAll("[data-p60-nav-toggle]")).find(a)??null,r=Array.from(t.querySelectorAll("[data-p60-nav-menu]")).find(a)??null;if(!c||!r)continue;let i={nav:e,item:t,toggle:c,menu:r,openedBy:null,lastPointer:"",openTimer:null,closeTimer:null},d=()=>A.has(i);c.setAttribute("aria-expanded","false"),r.id&&!c.hasAttribute("aria-controls")&&c.setAttribute("aria-controls",r.id),t.addEventListener("mouseenter",()=>{x()&&(i.closeTimer!==null&&(window.clearTimeout(i.closeTimer),i.closeTimer=null),!d()&&i.openTimer===null&&(i.openTimer=window.setTimeout(()=>{i.openTimer=null,w(i,"hover")},X)))}),t.addEventListener("mouseleave",()=>{x()&&(i.openTimer!==null&&(window.clearTimeout(i.openTimer),i.openTimer=null),d()&&i.openedBy==="hover"&&i.closeTimer===null&&(i.closeTimer=window.setTimeout(()=>{i.closeTimer=null,E(i)},j)))}),c.addEventListener("pointerdown",l=>{i.lastPointer=l.pointerType??""}),c.addEventListener("click",l=>{let f=l.detail===0||i.lastPointer==="touch"||i.lastPointer==="pen"||!x();if(!d()){l.preventDefault(),l.stopPropagation(),w(i,"toggle");return}!f&&i.openedBy==="hover"||(l.preventDefault(),l.stopPropagation(),E(i))}),c.addEventListener("keydown",l=>{l.key==="ArrowDown"&&(l.preventDefault(),d()||w(i,"toggle"),r.querySelector(z)?.focus())}),t.addEventListener("keydown",l=>{l.key==="Escape"&&d()&&(l.stopPropagation(),E(i,!0))}),t.addEventListener("focusin",l=>{l.target instanceof Node&&r.contains(l.target)&&!d()&&w(i,"focus")}),t.addEventListener("focusout",l=>{let f=l.relatedTarget;f instanceof Node&&!t.contains(f)&&d()&&E(i)})}}let s=Array.from(n.querySelectorAll("[data-p60-nav-burger]")).filter(e=>!y(e,"nav-burger"));for(let e of s){let o=e.getAttribute("aria-controls")||e.getAttribute("data-p60-nav-burger")||"",t=o?document.getElementById(o):null;if(!t)continue;let a=()=>t.classList.contains("is-open"),c=r=>{if(t.classList.toggle("is-open",r),e.classList.toggle("is-open",r),e.setAttribute("aria-expanded",String(r)),!r)for(let i of Array.from(A))t.contains(i.item)&&E(i)};e.setAttribute("aria-expanded","false"),e.addEventListener("click",r=>{r.stopPropagation(),c(!a())}),t.addEventListener("click",r=>{r.target instanceof Element&&r.target.closest("a")&&c(!1)}),document.addEventListener("keydown",r=>{r.key==="Escape"&&a()&&(c(!1),e.focus())}),document.addEventListener("click",r=>{a()&&r.target instanceof Node&&!t.contains(r.target)&&!e.contains(r.target)&&c(!1)}),window.addEventListener("resize",()=>{a()&&e.offsetParent===null&&c(!1)})}k||(k=!0,document.addEventListener("click",e=>{for(let o of Array.from(A))(!(e.target instanceof Node)||!o.item.contains(e.target))&&E(o)}))}function G(n=document){document.documentElement.classList.add("p60-js"),O(n),D(n),B(n),F(n),_(n),R(n),Y(n),$(n),K(n),V(n),U(n)}return C(W);})();
|
|
2
|
+
"use strict";var p60Behaviors=(()=>{var x=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var q=Object.prototype.hasOwnProperty;var I=(n,l)=>{for(var e in l)x(n,e,{get:l[e],enumerable:!0})},C=(n,l,e,o)=>{if(l&&typeof l=="object"||typeof l=="function")for(let t of P(l))!q.call(n,t)&&t!==e&&x(n,t,{get:()=>l[t],enumerable:!(o=H(l,t))||o.enumerable});return n};var F=n=>C(x({},"__esModule",{value:!0}),n);var Q={};I(Q,{initBehaviors:()=>J});var L=()=>window.matchMedia("(prefers-reduced-motion: reduce)").matches;function b(n,l){let e=`data-p60-bound-${l}`;return n.hasAttribute(e)?!0:(n.setAttribute(e,""),!1)}function T(n,l){if(n.length===0)return;if(L()||!("IntersectionObserver"in window)){n.forEach(l);return}let e=new IntersectionObserver(o=>{for(let t of o)t.isIntersecting&&(e.unobserve(t.target),l(t.target))},{rootMargin:"0px 0px -10% 0px",threshold:.15});n.forEach(o=>e.observe(o))}function O(n){let l=Array.from(n.querySelectorAll("[data-p60-reveal-group]")).filter(o=>!b(o,"reveal-group"));for(let o of l)Array.from(o.children).forEach((t,a)=>{t.style.setProperty("--p60-reveal-index",String(a)),t.classList.add("p60-reveal-child")});T(l,o=>o.classList.add("is-revealed"));let e=Array.from(n.querySelectorAll("[data-p60-reveal]")).filter(o=>!b(o,"reveal"));T(e,o=>o.classList.add("is-revealed"))}var B=/\d[\d, ]*(?:\.\d+)?/;function D(n){let l=Array.from(n.querySelectorAll("[data-p60-count]")).filter(e=>!b(e,"count"));T(l,e=>{e.classList.add("is-revealed");let o=e.textContent??"",t=B.exec(o);if(!t)return;let a=t[0].replace(/[, ]+$/,""),c=o.slice(0,t.index),r=o.slice(t.index+a.length),i=/[, ]/.test(a),d=a.includes(".")?a.length-a.indexOf(".")-1:0,s=Number.parseFloat(a.replace(/[, ]/g,"")),f=Number.parseFloat(e.getAttribute("data-p60-count")??""),g=Number.isFinite(f)?f:s;if(!Number.isFinite(g)||L())return;let u=Math.min(Number.parseInt(e.getAttribute("data-p60-count-duration")??"1200",10)||1200,4e3),p=new Intl.NumberFormat(document.documentElement.lang||void 0,{useGrouping:i,minimumFractionDigits:d,maximumFractionDigits:d}),m=performance.now(),h=v=>{let y=Math.min((v-m)/u,1),k=1-Math.pow(1-y,3);e.textContent=y<1?c+p.format(g*k)+r:o,y<1&&requestAnimationFrame(h)};requestAnimationFrame(h)})}function _(n){let l=Array.from(n.querySelectorAll("[data-p60-progress]")).filter(e=>!b(e,"progress"));if(!L()){for(let e of l){let o=e.style.width||getComputedStyle(e).width;e.style.transition="none",e.style.width="0px",e.offsetWidth,e.style.transition="width 1.1s cubic-bezier(0.22, 1, 0.36, 1)",e.dataset.p60ProgressTarget=o}T(l,e=>{e.classList.add("is-revealed"),e.style.width=e.dataset.p60ProgressTarget??""})}}function R(n){let l=Array.from(n.querySelectorAll("[data-p60-countdown]")).filter(e=>!b(e,"countdown"));for(let e of l){let o=Date.parse(e.getAttribute("data-p60-until")??"");if(!Number.isFinite(o))continue;let t=e.getAttribute("data-p60-countdown")||"dhm",a=t==="dhms",c=()=>{let i=o-Date.now();if(i<=0){e.classList.add("is-elapsed");let m=e.getAttribute("data-p60-elapsed-text");m&&(e.textContent=m),window.clearInterval(r);return}let d=Math.floor(i/1e3),s=Math.floor(d/86400),f=Math.floor(d%86400/3600),g=Math.floor(d%3600/60),u=d%60,p=[];t.includes("d")&&s>0&&p.push(`${s}d`),p.push(`${f}h`,`${g}m`),a&&p.push(`${u}s`),e.textContent=p.join(" ")},r=window.setInterval(c,a?1e3:15e3);c()}}function V(n){let l=Array.from(n.querySelectorAll("[data-p60-accordion]")).filter(e=>!b(e,"accordion"));for(let e of l){let o=e.getAttribute("data-p60-accordion")!=="multi",t=Array.from(e.querySelectorAll("details"));for(let a of t){a.addEventListener("toggle",()=>{if(a.classList.toggle("is-open",a.open),a.open&&o)for(let i of t)i!==a&&i.open&&(i.open=!1)}),a.open&&a.classList.add("is-open");let r=a.querySelector("summary")?.nextElementSibling;r&&!L()&&a.addEventListener("toggle",()=>{if(!a.open)return;let i=r.scrollHeight;r.style.overflow="hidden",r.animate([{height:"0px",opacity:"0"},{height:`${i}px`,opacity:"1"}],{duration:260,easing:"ease-out"}).addEventListener("finish",()=>{r.style.overflow=""})})}}}function $(n){let l=Array.from(n.querySelectorAll("[data-p60-carousel]")).filter(e=>!b(e,"carousel"));for(let e of l){let o=Array.from(e.querySelectorAll("[data-p60-slide]"));if(o.length<2)continue;let t=Math.max(0,o.findIndex(m=>m.classList.contains("is-active"))),a=!1,c=[],r=document.createElement("nav");r.className="p60-carousel-dots",r.setAttribute("aria-label","Slides"),o.forEach((m,h)=>{let v=document.createElement("button");v.type="button",v.className="p60-carousel-dot",v.setAttribute("aria-label",`Go to slide ${h+1}`),v.addEventListener("click",()=>i(h,!0)),c.push(v),r.appendChild(v)}),e.appendChild(r),e.setAttribute("aria-roledescription","carousel"),e.hasAttribute("tabindex")||e.setAttribute("tabindex","0");let i=(m,h=!1)=>{t=(m+o.length)%o.length,o.forEach((v,y)=>{v.classList.toggle("is-active",y===t),y===t?(v.removeAttribute("aria-hidden"),v.removeAttribute("inert")):(v.setAttribute("aria-hidden","true"),v.setAttribute("inert",""))}),c.forEach((v,y)=>{v.classList.toggle("p60-carousel-dot--active",y===t),v.setAttribute("aria-current",y===t?"true":"false")}),e.style.setProperty("--p60-carousel-index",String(t)),h&&p()};e.querySelectorAll("[data-p60-carousel-prev]").forEach(m=>m.addEventListener("click",()=>i(t-1,!0))),e.querySelectorAll("[data-p60-carousel-next]").forEach(m=>m.addEventListener("click",()=>i(t+1,!0))),e.addEventListener("keydown",m=>{m.key==="ArrowLeft"&&i(t-1,!0),m.key==="ArrowRight"&&i(t+1,!0)});let d=0,s=0;e.addEventListener("pointerdown",m=>{d=m.clientX,s=m.clientY}),e.addEventListener("pointerup",m=>{let h=m.clientX-d,v=m.clientY-s;Math.abs(h)>40&&Math.abs(h)>Math.abs(v)&&i(t+(h<0?1:-1),!0)}),e.addEventListener("mouseenter",()=>{a=!0}),e.addEventListener("mouseleave",()=>{a=!1}),e.addEventListener("focusin",()=>{a=!0}),e.addEventListener("focusout",()=>{a=!1});let f,g=e.getAttribute("data-p60-carousel")==="auto"&&!L(),u=Math.max(Number.parseInt(e.getAttribute("data-p60-interval")??"6000",10)||6e3,3e3),p=()=>{f!==void 0&&window.clearInterval(f),g&&(f=window.setInterval(()=>{!a&&!document.hidden&&i(t+1)},u))};i(t),p()}}function Y(n){let l=Array.from(n.querySelectorAll("[data-p60-sticky-header]")).filter(e=>!b(e,"sticky-header"));for(let e of l){let o=e.getAttribute("data-p60-sticky-header")==="auto-hide",t=window.scrollY,a=!1,c=()=>{let r=window.scrollY;e.classList.toggle("is-condensed",r>24),o&&(r>160&&r>t?e.classList.add("is-hidden"):e.classList.remove("is-hidden")),t=r,a=!1};window.addEventListener("scroll",()=>{a||(a=!0,requestAnimationFrame(c))},{passive:!0}),c()}}function K(n){let l=Array.from(n.querySelectorAll("[data-p60-sticky-cta]")).filter(e=>!b(e,"sticky-cta"));for(let e of l){let o=Number.parseInt(e.getAttribute("data-p60-sticky-cta")??"480",10)||480,t=!1,a=()=>{e.classList.toggle("is-stuck",window.scrollY>o),t=!1};window.addEventListener("scroll",()=>{t||(t=!0,requestAnimationFrame(a))},{passive:!0}),a()}}function X(n){let l=Array.from(n.querySelectorAll("[data-p60-lightbox]")).filter(e=>!b(e,"lightbox"));for(let e of l){let o=Array.from(e.querySelectorAll("a[data-p60-lightbox-item]"));if(o.length===0)continue;let t=null,a=0,c=null,r=()=>{t?.remove(),t=null,e.classList.remove("is-open"),document.removeEventListener("keydown",d),c?.focus()},i=f=>{a=(f+o.length)%o.length;let g=o[a];if(!t)return;let u=t.querySelector(".p60-lightbox-img"),p=t.querySelector(".p60-lightbox-caption");u&&(u.src=g.href);let m=g.getAttribute("data-p60-caption")??g.querySelector("img")?.alt??"";p&&(p.textContent=m),u&&(u.alt=m)},d=f=>{if(f.key==="Escape"&&r(),f.key==="ArrowLeft"&&i(a-1),f.key==="ArrowRight"&&i(a+1),f.key==="Tab"&&t){let g=Array.from(t.querySelectorAll("button")),u=g.indexOf(document.activeElement),p=f.shiftKey?u<=0?g.length-1:u-1:u>=g.length-1?0:u+1;g[p]?.focus(),f.preventDefault()}},s=(f,g)=>{c=g,t=document.createElement("div"),t.className="p60-lightbox",t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),L()&&(t.style.transition="none"),t.innerHTML='<figure><img class="p60-lightbox-img" alt=""><figcaption class="p60-lightbox-caption"></figcaption></figure>';let u=(m,h,v)=>{let y=document.createElement("button");return y.type="button",y.className=m,y.setAttribute("aria-label",h),y.addEventListener("click",v),t.appendChild(y),y};o.length>1&&(u("p60-lightbox-prev","Previous image",()=>i(a-1)),u("p60-lightbox-next","Next image",()=>i(a+1)));let p=u("p60-lightbox-close","Close",r);t.addEventListener("click",m=>{m.target===t&&r()}),document.body.appendChild(t),e.classList.add("is-open"),document.addEventListener("keydown",d),i(f),p.focus()};o.forEach((f,g)=>f.addEventListener("click",u=>{u.preventDefault(),s(g,f)}))}}function z(n){let l=Array.from(n.querySelectorAll("[data-p60-tabs]")).filter(e=>!b(e,"tabs"));for(let e of l){let o=Array.from(e.querySelectorAll("[data-p60-tab]")),t=Array.from(e.querySelectorAll("[data-p60-panel]"));if(o.length===0||t.length===0)continue;let a=r=>t.find(i=>i.getAttribute("data-p60-panel")===r.getAttribute("data-p60-tab"));o[0].closest("[data-p60-tabs] > *")?.setAttribute("role","tablist");let c=(r,i=!1)=>{for(let d of o){let s=d===r;d.classList.toggle("is-active",s),d.setAttribute("aria-selected",s?"true":"false"),d.setAttribute("tabindex",s?"0":"-1")}for(let d of t){let s=d===a(r);d.classList.toggle("is-active",s),d.hidden=!s}i&&r.focus()};o.forEach((r,i)=>{r.setAttribute("role","tab"),r.addEventListener("click",d=>{d.preventDefault(),c(r)}),r.addEventListener("keydown",d=>{let s=d.key;s==="ArrowLeft"&&c(o[(i-1+o.length)%o.length],!0),s==="ArrowRight"&&c(o[(i+1)%o.length],!0),s==="Home"&&c(o[0],!0),s==="End"&&c(o[o.length-1],!0)})}),t.forEach(r=>r.setAttribute("role","tabpanel")),c(o.find(r=>r.classList.contains("is-active"))??o[0])}}var W=60,U=280,M=()=>window.matchMedia("(hover: hover)").matches,j='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',A=new Set,N=!1;function S(n){n.openTimer!==null&&(window.clearTimeout(n.openTimer),n.openTimer=null),n.closeTimer!==null&&(window.clearTimeout(n.closeTimer),n.closeTimer=null)}function E(n,l=!1){S(n);for(let e of Array.from(A))e!==n&&n.item.contains(e.item)&&E(e);n.item.classList.remove("is-open"),n.toggle.setAttribute("aria-expanded","false"),n.openedBy=null,A.delete(n),l&&n.toggle.focus()}function w(n,l){S(n);for(let e of Array.from(A))e!==n&&e.nav===n.nav&&!e.item.contains(n.item)&&E(e);n.item.classList.add("is-open"),n.toggle.setAttribute("aria-expanded","true"),n.openedBy=l,A.add(n)}function G(n){for(let e of Array.from(n.querySelectorAll("[data-p60-nav]"))){let o=Array.from(e.querySelectorAll("[data-p60-nav-item]")).filter(t=>t.closest("[data-p60-nav]")===e&&!b(t,"nav-item"));for(let t of o){let a=s=>s.closest("[data-p60-nav-item]")===t,c=Array.from(t.querySelectorAll("[data-p60-nav-toggle]")).find(a)??null,r=Array.from(t.querySelectorAll("[data-p60-nav-menu]")).find(a)??null;if(!c||!r)continue;let i={nav:e,item:t,toggle:c,menu:r,openedBy:null,lastPointer:"",openTimer:null,closeTimer:null},d=()=>A.has(i);c.setAttribute("aria-expanded","false"),r.id&&!c.hasAttribute("aria-controls")&&c.setAttribute("aria-controls",r.id),t.addEventListener("mouseenter",()=>{M()&&(i.closeTimer!==null&&(window.clearTimeout(i.closeTimer),i.closeTimer=null),!d()&&i.openTimer===null&&(i.openTimer=window.setTimeout(()=>{i.openTimer=null,w(i,"hover")},W)))}),t.addEventListener("mouseleave",()=>{M()&&(i.openTimer!==null&&(window.clearTimeout(i.openTimer),i.openTimer=null),d()&&i.openedBy==="hover"&&i.closeTimer===null&&(i.closeTimer=window.setTimeout(()=>{i.closeTimer=null,E(i)},U)))}),c.addEventListener("pointerdown",s=>{i.lastPointer=s.pointerType??""}),c.addEventListener("click",s=>{let f=s.detail===0||i.lastPointer==="touch"||i.lastPointer==="pen"||!M();if(!d()){s.preventDefault(),s.stopPropagation(),w(i,"toggle");return}!f&&i.openedBy==="hover"||(s.preventDefault(),s.stopPropagation(),E(i))}),c.addEventListener("keydown",s=>{s.key==="ArrowDown"&&(s.preventDefault(),d()||w(i,"toggle"),r.querySelector(j)?.focus())}),t.addEventListener("keydown",s=>{s.key==="Escape"&&d()&&(s.stopPropagation(),E(i,!0))}),t.addEventListener("focusin",s=>{s.target instanceof Node&&r.contains(s.target)&&!d()&&w(i,"focus")}),t.addEventListener("focusout",s=>{let f=s.relatedTarget;f instanceof Node&&!t.contains(f)&&d()&&E(i)})}if(!b(e,"nav-fit")){let a=u=>{for(let p=1;p<=3;p++)e.classList.toggle(`is-fit-${p}`,p<=u)},c=u=>{let p=u.getBoundingClientRect();return p.width>0||p.height>0?[u]:Array.from(u.children).flatMap(c)},r=u=>{let p=-1/0;for(let m of u.flatMap(c)){let h=m.getBoundingClientRect();if(p!==-1/0&&h.top>=p-2)return!0;p=Math.max(p,h.bottom)}return!1},i=()=>{if(e.scrollWidth>e.clientWidth+1||r(Array.from(e.children)))return!1;let u=e.parentElement;return!(u&&getComputedStyle(u).flexWrap==="wrap"&&r(Array.from(u.children)))},d=0,s=()=>{if(d=performance.now(),e.offsetParent===null||!getComputedStyle(e).flexDirection.startsWith("row")){a(0);return}a(0);let u=0;for(;!i()&&u<3;)a(++u);d=performance.now()},f=!1,g=()=>{f||(f=!0,requestAnimationFrame(()=>{f=!1,s()}))};window.addEventListener("resize",g,{passive:!0}),document.fonts?.ready.then(g).catch(()=>{}),document.fonts?.addEventListener("loadingdone",g),"ResizeObserver"in window&&new ResizeObserver(()=>{performance.now()-d>120&&g()}).observe(e),s()}}let l=Array.from(n.querySelectorAll("[data-p60-nav-burger]")).filter(e=>!b(e,"nav-burger"));for(let e of l){let o=e.getAttribute("aria-controls")||e.getAttribute("data-p60-nav-burger")||"",t=o?document.getElementById(o):null;if(!t)continue;let a=()=>t.classList.contains("is-open"),c=r=>{if(t.classList.toggle("is-open",r),e.classList.toggle("is-open",r),e.setAttribute("aria-expanded",String(r)),!r)for(let i of Array.from(A))t.contains(i.item)&&E(i)};e.setAttribute("aria-expanded","false"),e.addEventListener("click",r=>{r.stopPropagation(),c(!a())}),t.addEventListener("click",r=>{r.target instanceof Element&&r.target.closest("a")&&c(!1)}),document.addEventListener("keydown",r=>{r.key==="Escape"&&a()&&(c(!1),e.focus())}),document.addEventListener("click",r=>{a()&&r.target instanceof Node&&!t.contains(r.target)&&!e.contains(r.target)&&c(!1)}),window.addEventListener("resize",()=>{a()&&e.offsetParent===null&&c(!1)})}N||(N=!0,document.addEventListener("click",e=>{for(let o of Array.from(A))(!(e.target instanceof Node)||!o.item.contains(e.target))&&E(o)}))}function J(n=document){document.documentElement.classList.add("p60-js"),O(n),D(n),_(n),R(n),V(n),$(n),Y(n),K(n),X(n),z(n),G(n)}return F(Q);})();
|