edgepress 2026.9.6 → 2026.9.8
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/README.md +2 -2
- package/config.yml +110 -63
- package/content/pages/home/en.md +9 -1
- package/content/pages/home/zh-cn.md +9 -1
- package/content/pages/plugin-development/en.md +5 -4
- package/content/pages/plugin-development/zh-cn.md +5 -4
- package/content/pages/privacy-policy/en.md +7 -4
- package/content/pages/privacy-policy/zh-cn.md +7 -4
- package/content/pages/theme-development/en.md +1 -0
- package/content/pages/theme-development/zh-cn.md +1 -0
- package/content/posts/2026-09-23-edgepress-on-the-edge/en.md +9 -1
- package/content/posts/2026-09-23-edgepress-on-the-edge/zh-cn.md +9 -1
- package/content/posts/2026-09-25-edgepress-release-2026-9-6/en.md +2 -2
- package/content/posts/2026-09-25-edgepress-release-2026-9-6/zh-cn.md +2 -2
- package/content/posts/2026-09-26-edgepress-release-2026-9-7/en.md +26 -0
- package/content/posts/2026-09-26-edgepress-release-2026-9-7/zh-cn.md +26 -0
- package/content/posts/2026-09-26-edgepress-release-2026-9-8/en.md +26 -0
- package/content/posts/2026-09-26-edgepress-release-2026-9-8/zh-cn.md +26 -0
- package/languages/base/en.json +7 -2
- package/languages/packs/zh-CN.json +7 -2
- package/package.json +2 -3
- package/plugins/consent/index.js +4 -2
- package/project-compatibility.json +19 -3
- package/src/build.js +5 -4
- package/src/cli.js +1 -11
- package/src/config.js +72 -14
- package/src/content.js +22 -1
- package/src/generators.js +25 -20
- package/src/i18n.js +6 -0
- package/src/markdown.js +88 -9
- package/src/page-blocks.js +61 -16
- package/src/page-check.js +73 -24
- package/src/report-visuals.js +111 -16
- package/static/edgepress/brand/mascot-209.webp +0 -0
- package/static/edgepress/brand/mascot-418.png +0 -0
- package/static/edgepress/brand/mascot-418.webp +0 -0
- package/static/edgepress/plugins/consent/manager.js +204 -71
- package/static/edgepress/plugins/statistics/cloudflare-web-analytics.js +1 -0
- package/themes/atelier/assets/style.css +50 -19
- package/themes/default/assets/style.css +50 -19
- package/themes/signal/assets/style.css +50 -19
- package/CHANGELOG.txt +0 -12
|
@@ -21,104 +21,171 @@ function initialize(config) {
|
|
|
21
21
|
const privacy = config.privacy || {};
|
|
22
22
|
const integrations = Array.isArray(privacy.integrations) ? privacy.integrations : [];
|
|
23
23
|
const ui = config.ui || {};
|
|
24
|
+
const locale = config.siteLanguage || document.documentElement.lang || 'en';
|
|
25
|
+
const defaultLocale = config.defaultLocale || 'en';
|
|
24
26
|
const root = document.createElement('div');
|
|
25
27
|
root.className = 'privacy-manager';
|
|
28
|
+
root.setAttribute('data-consent-ui', 'true');
|
|
26
29
|
|
|
27
|
-
const settingsButton =
|
|
28
|
-
settingsButton.
|
|
29
|
-
settingsButton.
|
|
30
|
-
settingsButton.textContent = ui.privacySettings || 'Privacy settings';
|
|
30
|
+
const settingsButton = makeButton(ui.privacySettings || 'Privacy settings', 'privacy-settings-button', 'settings');
|
|
31
|
+
settingsButton.setAttribute('aria-expanded', 'false');
|
|
32
|
+
settingsButton.setAttribute('aria-controls', 'privacy-panel');
|
|
31
33
|
|
|
32
34
|
const panel = document.createElement('section');
|
|
35
|
+
panel.id = 'privacy-panel';
|
|
33
36
|
panel.className = 'privacy-panel';
|
|
34
37
|
panel.setAttribute('role', 'dialog');
|
|
35
38
|
panel.setAttribute('aria-modal', 'false');
|
|
36
39
|
panel.setAttribute('aria-labelledby', 'privacy-panel-title');
|
|
37
|
-
panel.lang =
|
|
40
|
+
panel.lang = locale;
|
|
38
41
|
panel.hidden = true;
|
|
39
42
|
|
|
43
|
+
const close = makeButton(ui.closePrivacy || 'Close settings', 'privacy-close', 'close');
|
|
44
|
+
close.setAttribute('aria-label', ui.closePrivacy || 'Close settings');
|
|
40
45
|
const heading = document.createElement('h2');
|
|
41
46
|
heading.id = 'privacy-panel-title';
|
|
42
47
|
heading.tabIndex = -1;
|
|
43
|
-
heading.textContent = ui.privacyNotice || '
|
|
48
|
+
heading.textContent = ui.privacyNotice || 'Privacy choices';
|
|
44
49
|
const intro = document.createElement('p');
|
|
45
|
-
intro.
|
|
46
|
-
|
|
47
|
-
details.className = 'privacy-details';
|
|
48
|
-
details.setAttribute('aria-label', ui.optionalServices || 'Optional services');
|
|
49
|
-
const actions = document.createElement('div');
|
|
50
|
-
actions.className = 'privacy-actions';
|
|
51
|
-
const close = makeButton(ui.closePrivacy || 'Close settings', 'privacy-close');
|
|
52
|
-
|
|
53
|
-
const accept = makeButton(ui.acceptOptional || 'Accept all', 'privacy-accept');
|
|
54
|
-
const reject = makeButton(ui.rejectOptional || 'Reject optional', 'privacy-reject');
|
|
55
|
-
const save = makeButton(ui.savePreferences || 'Save choices', 'privacy-save');
|
|
56
|
-
actions.append(accept, reject, save);
|
|
57
|
-
panel.append(close, heading, intro, details);
|
|
58
|
-
if (privacy.controller?.name || privacy.controller?.contact) {
|
|
59
|
-
const controller = document.createElement('p');
|
|
60
|
-
controller.className = 'privacy-controller';
|
|
61
|
-
controller.textContent = (ui.privacyController || 'Site operator') + ': ' + [privacy.controller.name, privacy.controller.contact].filter(Boolean).join(' · ');
|
|
62
|
-
panel.append(controller);
|
|
63
|
-
}
|
|
64
|
-
if (privacy.policyUrl) {
|
|
65
|
-
const policy = document.createElement('a');
|
|
66
|
-
policy.href = privacy.policyUrl;
|
|
67
|
-
policy.textContent = ui.privacyPolicy || 'Privacy policy';
|
|
68
|
-
policy.className = 'privacy-policy-link';
|
|
69
|
-
panel.append(policy);
|
|
70
|
-
}
|
|
71
|
-
panel.append(actions);
|
|
72
|
-
root.append(settingsButton, panel);
|
|
73
|
-
document.body.append(root);
|
|
50
|
+
intro.className = 'privacy-intro';
|
|
51
|
+
intro.textContent = ui.privacyIntro || 'Optional services stay off until you choose.';
|
|
74
52
|
|
|
75
|
-
const
|
|
53
|
+
const preview = document.createElement('div');
|
|
54
|
+
preview.className = 'privacy-service-preview';
|
|
55
|
+
preview.setAttribute('aria-label', ui.optionalServices || 'Optional services');
|
|
56
|
+
const details = document.createElement('details');
|
|
57
|
+
details.className = 'privacy-details';
|
|
58
|
+
const summary = document.createElement('summary');
|
|
59
|
+
summary.textContent = ui.reviewDetails || 'Review data and service settings';
|
|
60
|
+
const serviceSettings = document.createElement('div');
|
|
61
|
+
serviceSettings.className = 'privacy-service-settings';
|
|
76
62
|
const checkboxes = new Map();
|
|
63
|
+
|
|
77
64
|
for (const integration of integrations) {
|
|
78
|
-
const
|
|
79
|
-
|
|
65
|
+
const category = translate(ui, 'plugin' + capitalize(integration.category || 'statistics'));
|
|
66
|
+
const name = localized(integration.name, locale, defaultLocale) || integration.provider;
|
|
67
|
+
const purpose = localized(integration.purpose, locale, defaultLocale);
|
|
68
|
+
const dataCategories = localized(integration.dataCategories, locale, defaultLocale);
|
|
69
|
+
const recipient = localized(integration.recipient, locale, defaultLocale);
|
|
70
|
+
const retention = localized(integration.retention, locale, defaultLocale);
|
|
71
|
+
|
|
72
|
+
const previewItem = document.createElement('article');
|
|
73
|
+
previewItem.className = 'privacy-preview-item';
|
|
74
|
+
const previewHeading = document.createElement('h3');
|
|
75
|
+
previewHeading.textContent = name;
|
|
76
|
+
const categoryText = document.createElement('span');
|
|
77
|
+
categoryText.className = 'privacy-category';
|
|
78
|
+
categoryText.textContent = category;
|
|
79
|
+
const previewPurpose = document.createElement('p');
|
|
80
|
+
previewPurpose.textContent = purpose;
|
|
81
|
+
previewItem.append(previewHeading, categoryText, previewPurpose);
|
|
82
|
+
preview.append(previewItem);
|
|
83
|
+
|
|
84
|
+
const item = document.createElement('article');
|
|
85
|
+
item.className = 'privacy-service-setting';
|
|
86
|
+
const toggle = document.createElement('label');
|
|
87
|
+
toggle.className = 'privacy-service-toggle';
|
|
80
88
|
const checkbox = document.createElement('input');
|
|
81
89
|
checkbox.type = 'checkbox';
|
|
82
90
|
checkbox.value = integration.id;
|
|
83
|
-
checkbox.
|
|
84
|
-
|
|
91
|
+
checkbox.setAttribute('role', 'switch');
|
|
92
|
+
checkbox.checked = false;
|
|
93
|
+
const toggleText = document.createElement('span');
|
|
94
|
+
toggleText.className = 'privacy-service-toggle-text';
|
|
85
95
|
const title = document.createElement('strong');
|
|
86
|
-
title.textContent =
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
title.textContent = name;
|
|
97
|
+
const categoryLabel = document.createElement('span');
|
|
98
|
+
categoryLabel.className = 'privacy-category';
|
|
99
|
+
categoryLabel.textContent = category;
|
|
100
|
+
toggleText.append(title, categoryLabel);
|
|
101
|
+
toggle.append(checkbox, toggleText);
|
|
102
|
+
item.append(toggle, disclosureList(ui, [
|
|
103
|
+
['servicePurpose', purpose],
|
|
104
|
+
['serviceDataCategories', dataCategories],
|
|
105
|
+
['serviceRecipient', recipient],
|
|
106
|
+
['serviceRetention', retention]
|
|
107
|
+
]));
|
|
108
|
+
serviceSettings.append(item);
|
|
97
109
|
checkboxes.set(integration.id, checkbox);
|
|
98
110
|
}
|
|
111
|
+
|
|
99
112
|
if (!integrations.length) {
|
|
100
113
|
const empty = document.createElement('p');
|
|
114
|
+
empty.className = 'privacy-empty';
|
|
101
115
|
empty.textContent = ui.noIntegrations || 'No optional services are configured.';
|
|
102
|
-
|
|
103
|
-
|
|
116
|
+
preview.append(empty);
|
|
117
|
+
serviceSettings.append(empty.cloneNode(true));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
details.append(summary, serviceSettings);
|
|
121
|
+
const essential = document.createElement('p');
|
|
122
|
+
essential.className = 'privacy-essential';
|
|
123
|
+
essential.textContent = (ui.essentialStorage || 'Your choice is saved in this browser for up to {days} days.')
|
|
124
|
+
.replace('{days}', String(privacy.consent?.expiresDays || 180));
|
|
125
|
+
|
|
126
|
+
const operator = privacy.controller || {};
|
|
127
|
+
const controller = document.createElement('p');
|
|
128
|
+
controller.className = 'privacy-controller';
|
|
129
|
+
const operatorDetails = [operator.name, operator.contact].filter(Boolean).join(' · ');
|
|
130
|
+
controller.textContent = operatorDetails ? (ui.privacyController || 'Site operator') + ': ' + operatorDetails : '';
|
|
131
|
+
const policy = document.createElement('a');
|
|
132
|
+
policy.href = privacy.policyUrl || '#';
|
|
133
|
+
policy.textContent = ui.privacyPolicy || 'Privacy policy';
|
|
134
|
+
policy.className = 'privacy-policy-link';
|
|
135
|
+
if (!privacy.policyUrl) policy.hidden = true;
|
|
136
|
+
|
|
137
|
+
const actions = document.createElement('div');
|
|
138
|
+
actions.className = 'privacy-actions';
|
|
139
|
+
const reject = makeButton(ui.rejectOptional || 'Reject optional', 'privacy-reject', 'reject');
|
|
140
|
+
const manage = makeButton(ui.managePrivacy || 'Manage', 'privacy-manage', 'manage');
|
|
141
|
+
const accept = makeButton(ui.acceptOptional || 'Accept all', 'privacy-accept', 'accept');
|
|
142
|
+
actions.append(reject, manage, accept);
|
|
143
|
+
const save = makeButton(ui.savePreferences || 'Save choices', 'privacy-save', 'save');
|
|
144
|
+
save.disabled = !integrations.length;
|
|
145
|
+
serviceSettings.append(save);
|
|
146
|
+
|
|
147
|
+
panel.append(close, heading, intro, preview, details, essential);
|
|
148
|
+
if (controller.textContent) panel.append(controller);
|
|
149
|
+
panel.append(policy, actions);
|
|
150
|
+
root.append(settingsButton, panel);
|
|
151
|
+
document.body.append(root);
|
|
152
|
+
|
|
153
|
+
const saved = readChoice(privacy);
|
|
154
|
+
for (const [id, checkbox] of checkboxes) checkbox.checked = Boolean(saved?.allowed.includes(id));
|
|
155
|
+
if (!integrations.length) {
|
|
104
156
|
reject.disabled = true;
|
|
105
|
-
|
|
157
|
+
accept.disabled = true;
|
|
158
|
+
manage.disabled = true;
|
|
106
159
|
}
|
|
107
160
|
|
|
108
161
|
settingsButton.addEventListener('click', () => {
|
|
109
162
|
panel.hidden = !panel.hidden;
|
|
110
|
-
|
|
163
|
+
settingsButton.setAttribute('aria-expanded', String(!panel.hidden));
|
|
164
|
+
if (!panel.hidden) heading.focus();
|
|
165
|
+
});
|
|
166
|
+
close.addEventListener('click', () => closePanel());
|
|
167
|
+
manage.addEventListener('click', () => {
|
|
168
|
+
details.open = true;
|
|
169
|
+
details.querySelector('summary')?.focus();
|
|
111
170
|
});
|
|
112
|
-
close.addEventListener('click', () => { panel.hidden = true; settingsButton.focus(); });
|
|
113
|
-
accept.addEventListener('click', () => saveChoice(integrations.map((item) => item.id)));
|
|
114
171
|
reject.addEventListener('click', () => saveChoice([]));
|
|
172
|
+
accept.addEventListener('click', () => saveChoice(integrations.map((item) => item.id)));
|
|
115
173
|
save.addEventListener('click', () => saveChoice([...checkboxes].filter(([, checkbox]) => checkbox.checked).map(([id]) => id)));
|
|
174
|
+
panel.addEventListener('keydown', (event) => {
|
|
175
|
+
if (event.key === 'Escape' && !panel.hidden) closePanel();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
function closePanel() {
|
|
179
|
+
panel.hidden = true;
|
|
180
|
+
settingsButton.setAttribute('aria-expanded', 'false');
|
|
181
|
+
settingsButton.focus();
|
|
182
|
+
}
|
|
116
183
|
|
|
117
184
|
function saveChoice(allowed) {
|
|
118
185
|
const previous = readChoice(privacy);
|
|
119
186
|
const next = makeChoice(privacy, allowed);
|
|
120
187
|
persistChoice(next);
|
|
121
|
-
|
|
188
|
+
closePanel();
|
|
122
189
|
if (previous && previous.allowed.some((id) => !next.allowed.includes(id))) {
|
|
123
190
|
intro.textContent = ui.consentReload || 'Your choice was saved. Reloading to apply the updated settings.';
|
|
124
191
|
window.location.reload();
|
|
@@ -128,28 +195,94 @@ function initialize(config) {
|
|
|
128
195
|
}
|
|
129
196
|
|
|
130
197
|
if (saved) activate(saved.allowed);
|
|
131
|
-
else if (integrations.length)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
198
|
+
else if (integrations.length) {
|
|
199
|
+
panel.hidden = false;
|
|
200
|
+
settingsButton.setAttribute('aria-expanded', 'true');
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function disclosureList(ui, entries) {
|
|
205
|
+
const list = document.createElement('dl');
|
|
206
|
+
list.className = 'privacy-service-disclosures';
|
|
207
|
+
for (const [key, value] of entries) {
|
|
208
|
+
if (!value) continue;
|
|
209
|
+
const row = document.createElement('div');
|
|
210
|
+
const term = document.createElement('dt');
|
|
211
|
+
term.textContent = translate(ui, key);
|
|
212
|
+
const description = document.createElement('dd');
|
|
213
|
+
description.textContent = value;
|
|
214
|
+
row.append(term, description);
|
|
215
|
+
list.append(row);
|
|
139
216
|
}
|
|
217
|
+
return list;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function translate(ui, key) {
|
|
221
|
+
return ui[key] || key;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function localized(value, locale, defaultLocale) {
|
|
225
|
+
if (typeof value === 'string') return value;
|
|
226
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return '';
|
|
227
|
+
return value[locale] || value[defaultLocale] || Object.values(value)[0] || '';
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function capitalize(value) {
|
|
231
|
+
return String(value).charAt(0).toUpperCase() + String(value).slice(1);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function makeButton(label, className, iconName) {
|
|
235
|
+
const button = document.createElement('button');
|
|
236
|
+
button.type = 'button';
|
|
237
|
+
button.className = className;
|
|
238
|
+
button.append(makeIcon(iconName), document.createTextNode(label));
|
|
239
|
+
return button;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function makeIcon(name) {
|
|
243
|
+
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
244
|
+
svg.setAttribute('viewBox', '0 0 24 24');
|
|
245
|
+
svg.setAttribute('aria-hidden', 'true');
|
|
246
|
+
svg.setAttribute('focusable', 'false');
|
|
247
|
+
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
248
|
+
const paths = {
|
|
249
|
+
settings: 'M4 6h16M4 12h16M4 18h16M8 4v4m8 2v4m-5 2v4',
|
|
250
|
+
manage: 'M4 6h16M4 12h16M4 18h16M8 4v4m8 2v4m-5 2v4',
|
|
251
|
+
accept: 'm5 12 4 4L19 6',
|
|
252
|
+
reject: 'm6 6 12 12M18 6 6 18',
|
|
253
|
+
close: 'm6 6 12 12M18 6 6 18',
|
|
254
|
+
save: 'M5 12h14m-6-6 6 6-6 6'
|
|
255
|
+
};
|
|
256
|
+
path.setAttribute('d', paths[name] || paths.manage);
|
|
257
|
+
path.setAttribute('fill', 'none');
|
|
258
|
+
path.setAttribute('stroke', 'currentColor');
|
|
259
|
+
path.setAttribute('stroke-width', '2');
|
|
260
|
+
path.setAttribute('stroke-linecap', 'round');
|
|
261
|
+
path.setAttribute('stroke-linejoin', 'round');
|
|
262
|
+
svg.append(path);
|
|
263
|
+
return svg;
|
|
140
264
|
}
|
|
141
265
|
|
|
142
266
|
function makeChoice(privacy, allowed) {
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
-
|
|
267
|
+
const consent = privacy.consent || {};
|
|
268
|
+
const expiresAt = Date.now() + Math.max(1, Math.min(730, consent.expiresDays || 180)) * 86400000;
|
|
269
|
+
const fingerprint = JSON.stringify({ controller: privacy.controller, policyUrl: privacy.policyUrl, consent, integrations: privacy.integrations });
|
|
270
|
+
return {
|
|
271
|
+
proposedDate: consent.proposedDate || '',
|
|
272
|
+
effectiveDate: consent.effectiveDate || '',
|
|
273
|
+
fingerprint,
|
|
274
|
+
expiresAt,
|
|
275
|
+
allowed: [...new Set(allowed)]
|
|
276
|
+
};
|
|
146
277
|
}
|
|
147
278
|
|
|
148
279
|
function readChoice(privacy) {
|
|
149
280
|
try {
|
|
150
281
|
const saved = JSON.parse(localStorage.getItem(storageKey));
|
|
151
|
-
const
|
|
152
|
-
|
|
282
|
+
const consent = privacy.consent || {};
|
|
283
|
+
const fingerprint = JSON.stringify({ controller: privacy.controller, policyUrl: privacy.policyUrl, consent, integrations: privacy.integrations });
|
|
284
|
+
if (!saved || saved.proposedDate !== (consent.proposedDate || '') || saved.effectiveDate !== (consent.effectiveDate || '') ||
|
|
285
|
+
saved.fingerprint !== fingerprint || saved.expiresAt <= Date.now() || !Array.isArray(saved.allowed)) {
|
|
153
286
|
localStorage.removeItem(storageKey);
|
|
154
287
|
return null;
|
|
155
288
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export function load(integration) {
|
|
2
2
|
if (document.querySelector('script[data-edgepress-provider="cloudflare-web-analytics"]')) return;
|
|
3
3
|
const script = document.createElement('script');
|
|
4
|
+
script.type = 'module';
|
|
4
5
|
script.async = true;
|
|
5
6
|
script.src = 'https://static.cloudflareinsights.com/beacon.min.js';
|
|
6
7
|
script.dataset.cfBeacon = JSON.stringify({ token: integration.token });
|
|
@@ -19,25 +19,48 @@ body{display:flex;flex-direction:column;min-height:100vh}
|
|
|
19
19
|
@media(max-width:760px){.site-footer{width:calc(100% - 38px)}}
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
.privacy-manager{position:fixed;right:
|
|
23
|
-
.privacy-
|
|
24
|
-
.privacy-
|
|
25
|
-
.privacy-panel{
|
|
26
|
-
.privacy-
|
|
27
|
-
.privacy-panel
|
|
28
|
-
.privacy-panel
|
|
29
|
-
.privacy-
|
|
30
|
-
.privacy-
|
|
31
|
-
.privacy-
|
|
32
|
-
.privacy-
|
|
33
|
-
.privacy-
|
|
34
|
-
.privacy-
|
|
35
|
-
.privacy-
|
|
36
|
-
.privacy-
|
|
37
|
-
.privacy-
|
|
38
|
-
.privacy-
|
|
39
|
-
|
|
40
|
-
|
|
22
|
+
.privacy-manager{position:fixed;inset-inline-end:max(12px,env(safe-area-inset-right));inset-block-end:max(12px,env(safe-area-inset-bottom));z-index:1000;display:grid;align-content:end;gap:8px;box-sizing:border-box;width:min(30rem,calc(100vw - 24px));max-height:calc(100vh - 24px);max-height:calc(100dvh - 24px);color:var(--ink,#1d2824);font:14px/1.45 ui-sans-serif,system-ui,sans-serif;pointer-events:none;isolation:isolate}
|
|
23
|
+
.privacy-manager *{box-sizing:border-box}
|
|
24
|
+
.privacy-manager>*{min-width:0;pointer-events:auto}
|
|
25
|
+
.privacy-manager .privacy-settings-button,.privacy-manager .privacy-panel button{display:inline-flex;justify-content:center;align-items:center;gap:8px;min-width:0;min-height:46px;max-width:100%;padding:10px 12px;border:1px solid var(--line,#c7d0c9);border-radius:10px;background:var(--panel,#fff);color:var(--ink,#1d2824);font:inherit;font-weight:700;line-height:1.25;text-align:center;overflow-wrap:anywhere;cursor:pointer}
|
|
26
|
+
.privacy-manager .privacy-settings-button{order:1;justify-self:end;box-shadow:0 4px 18px #0002}
|
|
27
|
+
.privacy-manager .privacy-panel{position:relative;order:0;display:grid;gap:12px;width:100%;max-height:min(68vh,40rem);max-height:min(68dvh,40rem);overflow:auto;overscroll-behavior:contain;padding:18px;border:1px solid var(--line,#c7d0c9);border-radius:14px;background:var(--paper,#fff);color:var(--ink,#1d2824);box-shadow:0 12px 40px #0003}
|
|
28
|
+
.privacy-manager .privacy-panel[hidden]{display:none}
|
|
29
|
+
.privacy-manager .privacy-panel h2{margin:0;padding-inline-end:44px;font-size:1.15rem;line-height:1.3}
|
|
30
|
+
.privacy-manager .privacy-panel p{margin:0;overflow-wrap:anywhere}
|
|
31
|
+
.privacy-manager .privacy-panel .privacy-close{position:absolute;inset-block-start:8px;inset-inline-end:8px;width:44px;min-width:44px;min-height:44px;padding:8px}
|
|
32
|
+
.privacy-manager .privacy-panel .privacy-close svg{width:20px;height:20px}
|
|
33
|
+
.privacy-manager svg{width:18px;height:18px;flex:none}
|
|
34
|
+
.privacy-manager .privacy-intro,.privacy-manager .privacy-essential,.privacy-manager .privacy-controller{color:var(--muted,#536159)}
|
|
35
|
+
.privacy-manager .privacy-service-preview,.privacy-manager .privacy-service-settings{display:grid;gap:8px;min-width:0}
|
|
36
|
+
.privacy-manager .privacy-preview-item,.privacy-manager .privacy-service-setting{display:grid;gap:7px;min-width:0;padding:11px;border:1px solid var(--line,#c7d0c9);border-radius:10px;background:var(--panel,#fff)}
|
|
37
|
+
.privacy-manager .privacy-preview-item{grid-template-columns:minmax(0,1fr) auto;align-items:start}
|
|
38
|
+
.privacy-manager .privacy-preview-item h3{min-width:0;margin:0;font-size:.96rem;overflow-wrap:anywhere}
|
|
39
|
+
.privacy-manager .privacy-preview-item p{grid-column:1/-1;color:var(--muted,#536159)}
|
|
40
|
+
.privacy-manager .privacy-category{justify-self:start;max-width:100%;padding:2px 7px;border-radius:999px;background:color-mix(in srgb,var(--accent,#315e49) 12%,transparent);color:var(--ink,#1d2824);font-size:.78rem;overflow-wrap:anywhere}
|
|
41
|
+
.privacy-manager .privacy-details{min-width:0;margin:0;border-block:1px solid var(--line,#c7d0c9)}
|
|
42
|
+
.privacy-manager .privacy-details>summary{padding:10px 2px;font-weight:750;cursor:pointer}
|
|
43
|
+
.privacy-manager .privacy-details>summary:focus-visible{outline:3px solid var(--accent,#315e49);outline-offset:3px}
|
|
44
|
+
.privacy-manager .privacy-service-settings{padding-block-end:10px}
|
|
45
|
+
.privacy-manager .privacy-service-toggle{display:flex;align-items:center;gap:11px;min-width:0;cursor:pointer}
|
|
46
|
+
.privacy-manager .privacy-service-toggle input{position:relative;flex:none;width:42px;height:24px;margin:0;appearance:none;border:1px solid var(--line,#748079);border-radius:999px;background:var(--line,#748079);cursor:pointer}
|
|
47
|
+
.privacy-manager .privacy-service-toggle input::before{position:absolute;inset-block-start:2px;inset-inline-start:2px;width:18px;height:18px;border-radius:50%;background:var(--paper,#fff);content:"";transition:transform .16s ease}
|
|
48
|
+
.privacy-manager .privacy-service-toggle input:checked{border-color:var(--accent,#315e49);background:var(--accent,#315e49)}
|
|
49
|
+
.privacy-manager .privacy-service-toggle input:checked::before{transform:translateX(18px)}
|
|
50
|
+
.privacy-manager .privacy-service-toggle input:focus-visible{outline:3px solid var(--accent,#315e49);outline-offset:3px}
|
|
51
|
+
.privacy-manager .privacy-service-toggle-text{display:grid;gap:3px;min-width:0;overflow-wrap:anywhere}
|
|
52
|
+
.privacy-manager .privacy-service-toggle-text strong{font-size:.96rem}
|
|
53
|
+
.privacy-manager .privacy-service-disclosures{display:grid;gap:6px;margin:0}
|
|
54
|
+
.privacy-manager .privacy-service-disclosures>div{display:grid;grid-template-columns:minmax(5.5rem,.34fr) minmax(0,1fr);gap:8px;min-width:0}
|
|
55
|
+
.privacy-manager .privacy-service-disclosures dt{color:var(--muted,#536159);font-weight:650}
|
|
56
|
+
.privacy-manager .privacy-service-disclosures dd{min-width:0;margin:0;overflow-wrap:anywhere}
|
|
57
|
+
.privacy-manager .privacy-actions{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
|
|
58
|
+
.privacy-manager .privacy-panel .privacy-accept,.privacy-manager .privacy-panel .privacy-reject{border-color:var(--accent,#315e49);background:var(--accent,#315e49);color:var(--paper,#fff)}
|
|
59
|
+
.privacy-manager .privacy-panel .privacy-save,.privacy-manager .privacy-panel .privacy-manage{background:transparent}
|
|
60
|
+
.privacy-manager .privacy-panel button:disabled{opacity:.55;cursor:not-allowed}
|
|
61
|
+
.privacy-manager .privacy-policy-link{width:fit-content;max-width:100%;font-size:.9rem;overflow-wrap:anywhere}
|
|
62
|
+
.privacy-manager .privacy-policy-link:focus-visible,.privacy-manager .privacy-settings-button:focus-visible,.privacy-manager .privacy-panel button:focus-visible{outline:3px solid var(--accent,#315e49);outline-offset:3px}
|
|
63
|
+
@media(max-width:560px){.privacy-manager{inset-inline-start:max(12px,env(safe-area-inset-left));width:auto;max-width:none}.privacy-manager .privacy-panel{max-height:min(68vh,40rem);max-height:min(68dvh,40rem);padding:15px}.privacy-manager .privacy-actions{grid-template-columns:repeat(2,minmax(0,1fr));gap:7px}.privacy-manager .privacy-actions .privacy-manage{grid-column:1/-1;grid-row:1}.privacy-manager .privacy-actions .privacy-reject{grid-column:1;grid-row:2}.privacy-manager .privacy-actions .privacy-accept{grid-column:2;grid-row:2}.privacy-manager .privacy-panel .privacy-save{width:100%}}
|
|
41
64
|
.page-builder{display:grid;gap:24px}
|
|
42
65
|
.page-title h1{font-size:clamp(2rem,5vw,3.3rem);line-height:1.1;letter-spacing:-.04em}
|
|
43
66
|
.hero-block{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(180px,.8fr);gap:28px;padding:clamp(26px,5vw,54px);background:var(--panel);border:1px solid var(--line);margin:0 0 24px}
|
|
@@ -165,3 +188,11 @@ body{background:radial-gradient(ellipse at 88% 2%,#ffe5df 0,transparent 32%),var
|
|
|
165
188
|
.feature-icon{display:block;width:34px;height:34px;margin:0 0 10px;color:var(--accent);fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
|
|
166
189
|
.latest-posts-pagination{justify-content:flex-start;gap:16px;margin-top:18px}
|
|
167
190
|
.latest-posts-pagination a:last-child{margin-left:auto}
|
|
191
|
+
.hero-mascot-picture{display:block;width:min(100%,230px)}
|
|
192
|
+
.post-excerpt{max-width:72ch;color:var(--muted);font-size:.95rem;line-height:1.6}
|
|
193
|
+
.post-excerpt p{margin:.35rem 0 0}
|
|
194
|
+
.post-excerpt p:first-child{margin-top:0}
|
|
195
|
+
.post-excerpt a{color:inherit}
|
|
196
|
+
.post-content .markdown-video{margin:1.5rem 0}
|
|
197
|
+
.post-content .markdown-video video{display:block;width:100%;max-width:100%;height:auto;border-radius:10px;background:#101410}
|
|
198
|
+
.post-content .markdown-video figcaption{margin-top:.5rem;color:var(--muted);font-size:.9rem}
|
|
@@ -18,25 +18,48 @@ main{flex:1;min-height:0}
|
|
|
18
18
|
.ad-slot:empty{min-height:90px}.captcha-block{min-height:65px}
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
.privacy-manager{position:fixed;right:
|
|
22
|
-
.privacy-
|
|
23
|
-
.privacy-
|
|
24
|
-
.privacy-panel{
|
|
25
|
-
.privacy-
|
|
26
|
-
.privacy-panel
|
|
27
|
-
.privacy-panel
|
|
28
|
-
.privacy-
|
|
29
|
-
.privacy-
|
|
30
|
-
.privacy-
|
|
31
|
-
.privacy-
|
|
32
|
-
.privacy-
|
|
33
|
-
.privacy-
|
|
34
|
-
.privacy-
|
|
35
|
-
.privacy-
|
|
36
|
-
.privacy-
|
|
37
|
-
.privacy-
|
|
38
|
-
|
|
39
|
-
|
|
21
|
+
.privacy-manager{position:fixed;inset-inline-end:max(12px,env(safe-area-inset-right));inset-block-end:max(12px,env(safe-area-inset-bottom));z-index:1000;display:grid;align-content:end;gap:8px;box-sizing:border-box;width:min(30rem,calc(100vw - 24px));max-height:calc(100vh - 24px);max-height:calc(100dvh - 24px);color:var(--ink,#1d2824);font:14px/1.45 ui-sans-serif,system-ui,sans-serif;pointer-events:none;isolation:isolate}
|
|
22
|
+
.privacy-manager *{box-sizing:border-box}
|
|
23
|
+
.privacy-manager>*{min-width:0;pointer-events:auto}
|
|
24
|
+
.privacy-manager .privacy-settings-button,.privacy-manager .privacy-panel button{display:inline-flex;justify-content:center;align-items:center;gap:8px;min-width:0;min-height:46px;max-width:100%;padding:10px 12px;border:1px solid var(--line,#c7d0c9);border-radius:10px;background:var(--panel,#fff);color:var(--ink,#1d2824);font:inherit;font-weight:700;line-height:1.25;text-align:center;overflow-wrap:anywhere;cursor:pointer}
|
|
25
|
+
.privacy-manager .privacy-settings-button{order:1;justify-self:end;box-shadow:0 4px 18px #0002}
|
|
26
|
+
.privacy-manager .privacy-panel{position:relative;order:0;display:grid;gap:12px;width:100%;max-height:min(68vh,40rem);max-height:min(68dvh,40rem);overflow:auto;overscroll-behavior:contain;padding:18px;border:1px solid var(--line,#c7d0c9);border-radius:14px;background:var(--paper,#fff);color:var(--ink,#1d2824);box-shadow:0 12px 40px #0003}
|
|
27
|
+
.privacy-manager .privacy-panel[hidden]{display:none}
|
|
28
|
+
.privacy-manager .privacy-panel h2{margin:0;padding-inline-end:44px;font-size:1.15rem;line-height:1.3}
|
|
29
|
+
.privacy-manager .privacy-panel p{margin:0;overflow-wrap:anywhere}
|
|
30
|
+
.privacy-manager .privacy-panel .privacy-close{position:absolute;inset-block-start:8px;inset-inline-end:8px;width:44px;min-width:44px;min-height:44px;padding:8px}
|
|
31
|
+
.privacy-manager .privacy-panel .privacy-close svg{width:20px;height:20px}
|
|
32
|
+
.privacy-manager svg{width:18px;height:18px;flex:none}
|
|
33
|
+
.privacy-manager .privacy-intro,.privacy-manager .privacy-essential,.privacy-manager .privacy-controller{color:var(--muted,#536159)}
|
|
34
|
+
.privacy-manager .privacy-service-preview,.privacy-manager .privacy-service-settings{display:grid;gap:8px;min-width:0}
|
|
35
|
+
.privacy-manager .privacy-preview-item,.privacy-manager .privacy-service-setting{display:grid;gap:7px;min-width:0;padding:11px;border:1px solid var(--line,#c7d0c9);border-radius:10px;background:var(--panel,#fff)}
|
|
36
|
+
.privacy-manager .privacy-preview-item{grid-template-columns:minmax(0,1fr) auto;align-items:start}
|
|
37
|
+
.privacy-manager .privacy-preview-item h3{min-width:0;margin:0;font-size:.96rem;overflow-wrap:anywhere}
|
|
38
|
+
.privacy-manager .privacy-preview-item p{grid-column:1/-1;color:var(--muted,#536159)}
|
|
39
|
+
.privacy-manager .privacy-category{justify-self:start;max-width:100%;padding:2px 7px;border-radius:999px;background:color-mix(in srgb,var(--accent,#315e49) 12%,transparent);color:var(--ink,#1d2824);font-size:.78rem;overflow-wrap:anywhere}
|
|
40
|
+
.privacy-manager .privacy-details{min-width:0;margin:0;border-block:1px solid var(--line,#c7d0c9)}
|
|
41
|
+
.privacy-manager .privacy-details>summary{padding:10px 2px;font-weight:750;cursor:pointer}
|
|
42
|
+
.privacy-manager .privacy-details>summary:focus-visible{outline:3px solid var(--accent,#315e49);outline-offset:3px}
|
|
43
|
+
.privacy-manager .privacy-service-settings{padding-block-end:10px}
|
|
44
|
+
.privacy-manager .privacy-service-toggle{display:flex;align-items:center;gap:11px;min-width:0;cursor:pointer}
|
|
45
|
+
.privacy-manager .privacy-service-toggle input{position:relative;flex:none;width:42px;height:24px;margin:0;appearance:none;border:1px solid var(--line,#748079);border-radius:999px;background:var(--line,#748079);cursor:pointer}
|
|
46
|
+
.privacy-manager .privacy-service-toggle input::before{position:absolute;inset-block-start:2px;inset-inline-start:2px;width:18px;height:18px;border-radius:50%;background:var(--paper,#fff);content:"";transition:transform .16s ease}
|
|
47
|
+
.privacy-manager .privacy-service-toggle input:checked{border-color:var(--accent,#315e49);background:var(--accent,#315e49)}
|
|
48
|
+
.privacy-manager .privacy-service-toggle input:checked::before{transform:translateX(18px)}
|
|
49
|
+
.privacy-manager .privacy-service-toggle input:focus-visible{outline:3px solid var(--accent,#315e49);outline-offset:3px}
|
|
50
|
+
.privacy-manager .privacy-service-toggle-text{display:grid;gap:3px;min-width:0;overflow-wrap:anywhere}
|
|
51
|
+
.privacy-manager .privacy-service-toggle-text strong{font-size:.96rem}
|
|
52
|
+
.privacy-manager .privacy-service-disclosures{display:grid;gap:6px;margin:0}
|
|
53
|
+
.privacy-manager .privacy-service-disclosures>div{display:grid;grid-template-columns:minmax(5.5rem,.34fr) minmax(0,1fr);gap:8px;min-width:0}
|
|
54
|
+
.privacy-manager .privacy-service-disclosures dt{color:var(--muted,#536159);font-weight:650}
|
|
55
|
+
.privacy-manager .privacy-service-disclosures dd{min-width:0;margin:0;overflow-wrap:anywhere}
|
|
56
|
+
.privacy-manager .privacy-actions{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
|
|
57
|
+
.privacy-manager .privacy-panel .privacy-accept,.privacy-manager .privacy-panel .privacy-reject{border-color:var(--accent,#315e49);background:var(--accent,#315e49);color:var(--paper,#fff)}
|
|
58
|
+
.privacy-manager .privacy-panel .privacy-save,.privacy-manager .privacy-panel .privacy-manage{background:transparent}
|
|
59
|
+
.privacy-manager .privacy-panel button:disabled{opacity:.55;cursor:not-allowed}
|
|
60
|
+
.privacy-manager .privacy-policy-link{width:fit-content;max-width:100%;font-size:.9rem;overflow-wrap:anywhere}
|
|
61
|
+
.privacy-manager .privacy-policy-link:focus-visible,.privacy-manager .privacy-settings-button:focus-visible,.privacy-manager .privacy-panel button:focus-visible{outline:3px solid var(--accent,#315e49);outline-offset:3px}
|
|
62
|
+
@media(max-width:560px){.privacy-manager{inset-inline-start:max(12px,env(safe-area-inset-left));width:auto;max-width:none}.privacy-manager .privacy-panel{max-height:min(68vh,40rem);max-height:min(68dvh,40rem);padding:15px}.privacy-manager .privacy-actions{grid-template-columns:repeat(2,minmax(0,1fr));gap:7px}.privacy-manager .privacy-actions .privacy-manage{grid-column:1/-1;grid-row:1}.privacy-manager .privacy-actions .privacy-reject{grid-column:1;grid-row:2}.privacy-manager .privacy-actions .privacy-accept{grid-column:2;grid-row:2}.privacy-manager .privacy-panel .privacy-save{width:100%}}
|
|
40
63
|
/* Page blocks follow a section-and-widget layout, while articles keep their own reading column. */
|
|
41
64
|
body{max-width:none;padding:0 clamp(18px,4vw,56px)}
|
|
42
65
|
.site-header,main,.site-footer{width:min(100%,1240px);margin-inline:auto}
|
|
@@ -203,3 +226,11 @@ body{background:radial-gradient(ellipse at 92% 0%,#e9e9ff 0,transparent 33%),var
|
|
|
203
226
|
.feature-icon{display:block;width:34px;height:34px;margin:0 0 10px;color:var(--accent);fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
|
|
204
227
|
.latest-posts-pagination{justify-content:flex-start;gap:16px;margin-top:18px}
|
|
205
228
|
.latest-posts-pagination a:last-child{margin-left:auto}
|
|
229
|
+
.hero-mascot-picture{display:block;width:min(100%,230px)}
|
|
230
|
+
.post-excerpt{max-width:72ch;color:var(--muted);font-size:.95rem;line-height:1.6}
|
|
231
|
+
.post-excerpt p{margin:.35rem 0 0}
|
|
232
|
+
.post-excerpt p:first-child{margin-top:0}
|
|
233
|
+
.post-excerpt a{color:inherit}
|
|
234
|
+
.post-content .markdown-video{margin:1.5rem 0}
|
|
235
|
+
.post-content .markdown-video video{display:block;width:100%;max-width:100%;height:auto;border-radius:10px;background:#101410}
|
|
236
|
+
.post-content .markdown-video figcaption{margin-top:.5rem;color:var(--muted);font-size:.9rem}
|
|
@@ -18,25 +18,48 @@ main{flex:1;min-height:0}
|
|
|
18
18
|
.ad-slot:empty{min-height:90px}.captcha-block{min-height:65px}
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
.privacy-manager{position:fixed;right:
|
|
22
|
-
.privacy-
|
|
23
|
-
.privacy-
|
|
24
|
-
.privacy-panel{
|
|
25
|
-
.privacy-
|
|
26
|
-
.privacy-panel
|
|
27
|
-
.privacy-panel
|
|
28
|
-
.privacy-
|
|
29
|
-
.privacy-
|
|
30
|
-
.privacy-
|
|
31
|
-
.privacy-
|
|
32
|
-
.privacy-
|
|
33
|
-
.privacy-
|
|
34
|
-
.privacy-
|
|
35
|
-
.privacy-
|
|
36
|
-
.privacy-
|
|
37
|
-
.privacy-
|
|
38
|
-
|
|
39
|
-
|
|
21
|
+
.privacy-manager{position:fixed;inset-inline-end:max(12px,env(safe-area-inset-right));inset-block-end:max(12px,env(safe-area-inset-bottom));z-index:1000;display:grid;align-content:end;gap:8px;box-sizing:border-box;width:min(30rem,calc(100vw - 24px));max-height:calc(100vh - 24px);max-height:calc(100dvh - 24px);color:var(--ink,#1d2824);font:14px/1.45 ui-sans-serif,system-ui,sans-serif;pointer-events:none;isolation:isolate}
|
|
22
|
+
.privacy-manager *{box-sizing:border-box}
|
|
23
|
+
.privacy-manager>*{min-width:0;pointer-events:auto}
|
|
24
|
+
.privacy-manager .privacy-settings-button,.privacy-manager .privacy-panel button{display:inline-flex;justify-content:center;align-items:center;gap:8px;min-width:0;min-height:46px;max-width:100%;padding:10px 12px;border:1px solid var(--line,#c7d0c9);border-radius:10px;background:var(--panel,#fff);color:var(--ink,#1d2824);font:inherit;font-weight:700;line-height:1.25;text-align:center;overflow-wrap:anywhere;cursor:pointer}
|
|
25
|
+
.privacy-manager .privacy-settings-button{order:1;justify-self:end;box-shadow:0 4px 18px #0002}
|
|
26
|
+
.privacy-manager .privacy-panel{position:relative;order:0;display:grid;gap:12px;width:100%;max-height:min(68vh,40rem);max-height:min(68dvh,40rem);overflow:auto;overscroll-behavior:contain;padding:18px;border:1px solid var(--line,#c7d0c9);border-radius:14px;background:var(--paper,#fff);color:var(--ink,#1d2824);box-shadow:0 12px 40px #0003}
|
|
27
|
+
.privacy-manager .privacy-panel[hidden]{display:none}
|
|
28
|
+
.privacy-manager .privacy-panel h2{margin:0;padding-inline-end:44px;font-size:1.15rem;line-height:1.3}
|
|
29
|
+
.privacy-manager .privacy-panel p{margin:0;overflow-wrap:anywhere}
|
|
30
|
+
.privacy-manager .privacy-panel .privacy-close{position:absolute;inset-block-start:8px;inset-inline-end:8px;width:44px;min-width:44px;min-height:44px;padding:8px}
|
|
31
|
+
.privacy-manager .privacy-panel .privacy-close svg{width:20px;height:20px}
|
|
32
|
+
.privacy-manager svg{width:18px;height:18px;flex:none}
|
|
33
|
+
.privacy-manager .privacy-intro,.privacy-manager .privacy-essential,.privacy-manager .privacy-controller{color:var(--muted,#536159)}
|
|
34
|
+
.privacy-manager .privacy-service-preview,.privacy-manager .privacy-service-settings{display:grid;gap:8px;min-width:0}
|
|
35
|
+
.privacy-manager .privacy-preview-item,.privacy-manager .privacy-service-setting{display:grid;gap:7px;min-width:0;padding:11px;border:1px solid var(--line,#c7d0c9);border-radius:10px;background:var(--panel,#fff)}
|
|
36
|
+
.privacy-manager .privacy-preview-item{grid-template-columns:minmax(0,1fr) auto;align-items:start}
|
|
37
|
+
.privacy-manager .privacy-preview-item h3{min-width:0;margin:0;font-size:.96rem;overflow-wrap:anywhere}
|
|
38
|
+
.privacy-manager .privacy-preview-item p{grid-column:1/-1;color:var(--muted,#536159)}
|
|
39
|
+
.privacy-manager .privacy-category{justify-self:start;max-width:100%;padding:2px 7px;border-radius:999px;background:color-mix(in srgb,var(--accent,#315e49) 12%,transparent);color:var(--ink,#1d2824);font-size:.78rem;overflow-wrap:anywhere}
|
|
40
|
+
.privacy-manager .privacy-details{min-width:0;margin:0;border-block:1px solid var(--line,#c7d0c9)}
|
|
41
|
+
.privacy-manager .privacy-details>summary{padding:10px 2px;font-weight:750;cursor:pointer}
|
|
42
|
+
.privacy-manager .privacy-details>summary:focus-visible{outline:3px solid var(--accent,#315e49);outline-offset:3px}
|
|
43
|
+
.privacy-manager .privacy-service-settings{padding-block-end:10px}
|
|
44
|
+
.privacy-manager .privacy-service-toggle{display:flex;align-items:center;gap:11px;min-width:0;cursor:pointer}
|
|
45
|
+
.privacy-manager .privacy-service-toggle input{position:relative;flex:none;width:42px;height:24px;margin:0;appearance:none;border:1px solid var(--line,#748079);border-radius:999px;background:var(--line,#748079);cursor:pointer}
|
|
46
|
+
.privacy-manager .privacy-service-toggle input::before{position:absolute;inset-block-start:2px;inset-inline-start:2px;width:18px;height:18px;border-radius:50%;background:var(--paper,#fff);content:"";transition:transform .16s ease}
|
|
47
|
+
.privacy-manager .privacy-service-toggle input:checked{border-color:var(--accent,#315e49);background:var(--accent,#315e49)}
|
|
48
|
+
.privacy-manager .privacy-service-toggle input:checked::before{transform:translateX(18px)}
|
|
49
|
+
.privacy-manager .privacy-service-toggle input:focus-visible{outline:3px solid var(--accent,#315e49);outline-offset:3px}
|
|
50
|
+
.privacy-manager .privacy-service-toggle-text{display:grid;gap:3px;min-width:0;overflow-wrap:anywhere}
|
|
51
|
+
.privacy-manager .privacy-service-toggle-text strong{font-size:.96rem}
|
|
52
|
+
.privacy-manager .privacy-service-disclosures{display:grid;gap:6px;margin:0}
|
|
53
|
+
.privacy-manager .privacy-service-disclosures>div{display:grid;grid-template-columns:minmax(5.5rem,.34fr) minmax(0,1fr);gap:8px;min-width:0}
|
|
54
|
+
.privacy-manager .privacy-service-disclosures dt{color:var(--muted,#536159);font-weight:650}
|
|
55
|
+
.privacy-manager .privacy-service-disclosures dd{min-width:0;margin:0;overflow-wrap:anywhere}
|
|
56
|
+
.privacy-manager .privacy-actions{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
|
|
57
|
+
.privacy-manager .privacy-panel .privacy-accept,.privacy-manager .privacy-panel .privacy-reject{border-color:var(--accent,#315e49);background:var(--accent,#315e49);color:var(--paper,#fff)}
|
|
58
|
+
.privacy-manager .privacy-panel .privacy-save,.privacy-manager .privacy-panel .privacy-manage{background:transparent}
|
|
59
|
+
.privacy-manager .privacy-panel button:disabled{opacity:.55;cursor:not-allowed}
|
|
60
|
+
.privacy-manager .privacy-policy-link{width:fit-content;max-width:100%;font-size:.9rem;overflow-wrap:anywhere}
|
|
61
|
+
.privacy-manager .privacy-policy-link:focus-visible,.privacy-manager .privacy-settings-button:focus-visible,.privacy-manager .privacy-panel button:focus-visible{outline:3px solid var(--accent,#315e49);outline-offset:3px}
|
|
62
|
+
@media(max-width:560px){.privacy-manager{inset-inline-start:max(12px,env(safe-area-inset-left));width:auto;max-width:none}.privacy-manager .privacy-panel{max-height:min(68vh,40rem);max-height:min(68dvh,40rem);padding:15px}.privacy-manager .privacy-actions{grid-template-columns:repeat(2,minmax(0,1fr));gap:7px}.privacy-manager .privacy-actions .privacy-manage{grid-column:1/-1;grid-row:1}.privacy-manager .privacy-actions .privacy-reject{grid-column:1;grid-row:2}.privacy-manager .privacy-actions .privacy-accept{grid-column:2;grid-row:2}.privacy-manager .privacy-panel .privacy-save{width:100%}}
|
|
40
63
|
.page-builder{display:grid;gap:22px}.page-title h1{font-size:clamp(2rem,5vw,3.5rem);line-height:1.08;letter-spacing:-.04em}
|
|
41
64
|
.hero-block{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(190px,.8fr);align-items:center;gap:28px;padding:clamp(28px,6vw,70px);background:linear-gradient(145deg,#202a48,#171e35);border:1px solid var(--line);border-radius:18px;margin:0}
|
|
42
65
|
.hero-block:not(.hero-block--split){display:block}.hero-highlights{display:grid;gap:10px;list-style:none;padding:0}.hero-highlights li,.feature-card,.steps-widget li,.privacy-service-list li,.link-list li{padding:18px;background:var(--panel);border:1px solid var(--line);border-radius:12px}
|
|
@@ -158,3 +181,11 @@ body{background:radial-gradient(ellipse at 14% 0%,#302052 0,transparent 38%),var
|
|
|
158
181
|
.feature-icon{display:block;width:34px;height:34px;margin:0 0 10px;color:var(--accent);fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
|
|
159
182
|
.latest-posts-pagination{justify-content:flex-start;gap:16px;margin-top:18px}
|
|
160
183
|
.latest-posts-pagination a:last-child{margin-left:auto}
|
|
184
|
+
.hero-mascot-picture{display:block;width:min(100%,230px)}
|
|
185
|
+
.post-excerpt{max-width:72ch;color:var(--muted);font-size:.95rem;line-height:1.6}
|
|
186
|
+
.post-excerpt p{margin:.35rem 0 0}
|
|
187
|
+
.post-excerpt p:first-child{margin-top:0}
|
|
188
|
+
.post-excerpt a{color:inherit}
|
|
189
|
+
.post-content .markdown-video{margin:1.5rem 0}
|
|
190
|
+
.post-content .markdown-video video{display:block;width:100%;max-width:100%;height:auto;border-radius:10px;background:#101410}
|
|
191
|
+
.post-content .markdown-video figcaption{margin-top:.5rem;color:var(--muted);font-size:.9rem}
|
package/CHANGELOG.txt
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
EdgePress Changelog
|
|
2
|
-
===================
|
|
3
|
-
|
|
4
|
-
2026.9.6 — 2026-09-25
|
|
5
|
-
---------------------
|
|
6
|
-
|
|
7
|
-
- Added a shared, locally hosted SVG icon library with 22 reusable icons. Theme navigation uses common icons, and feature-grid cards can opt into named icons.
|
|
8
|
-
- Added the EdgePress page mark, folded-paper sparrow mascot, and a 1200 × 630 Open Graph image. Themes include the mark as their favicon and show the mascot on the homepage.
|
|
9
|
-
- Added accessible older/newer archive navigation for paginated homepage post lists.
|
|
10
|
-
- Added localized post author metadata, visible bylines, and matching BlogPosting structured data.
|
|
11
|
-
- Removed stale demo-video references from page and post content. No video assets are generated by this release.
|
|
12
|
-
- Kept icons, branding, and share assets local, with no new runtime dependencies or third-party asset requests.
|