edgepress 2026.9.4 → 2026.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.txt +12 -0
  2. package/README.md +6 -4
  3. package/config.yml +11 -6
  4. package/content/pages/home/en.md +7 -0
  5. package/content/pages/home/zh-cn.md +8 -1
  6. package/content/pages/privacy-policy/en.md +1 -1
  7. package/content/pages/privacy-policy/zh-cn.md +1 -1
  8. package/content/pages/quick-start/en.md +3 -0
  9. package/content/pages/quick-start/zh-cn.md +3 -0
  10. package/content/pages/theme-development/en.md +23 -0
  11. package/content/pages/theme-development/zh-cn.md +23 -0
  12. package/content/posts/2026-09-23-edgepress-on-the-edge/en.md +3 -1
  13. package/content/posts/2026-09-23-edgepress-on-the-edge/zh-cn.md +3 -1
  14. package/content/posts/2026-09-24-edgepress-release-2026-9-1/en.md +2 -0
  15. package/content/posts/2026-09-24-edgepress-release-2026-9-1/zh-cn.md +2 -0
  16. package/content/posts/2026-09-25-edgepress-release-2026-9-2/en.md +2 -0
  17. package/content/posts/2026-09-25-edgepress-release-2026-9-2/zh-cn.md +2 -0
  18. package/content/posts/2026-09-25-edgepress-release-2026-9-3/en.md +2 -0
  19. package/content/posts/2026-09-25-edgepress-release-2026-9-3/zh-cn.md +2 -0
  20. package/content/posts/2026-09-25-edgepress-release-2026-9-4/en.md +2 -0
  21. package/content/posts/2026-09-25-edgepress-release-2026-9-4/zh-cn.md +2 -0
  22. package/content/posts/2026-09-25-edgepress-release-2026-9-5/en.md +19 -0
  23. package/content/posts/2026-09-25-edgepress-release-2026-9-5/zh-cn.md +19 -0
  24. package/content/posts/2026-09-25-edgepress-release-2026-9-6/en.md +31 -0
  25. package/content/posts/2026-09-25-edgepress-release-2026-9-6/zh-cn.md +31 -0
  26. package/languages/base/en.json +2 -0
  27. package/languages/packs/zh-CN.json +2 -0
  28. package/package.json +4 -2
  29. package/project-compatibility.json +17 -2
  30. package/src/cli.js +7 -2
  31. package/src/content.js +33 -0
  32. package/src/generators.js +111 -14
  33. package/src/icons.js +16 -0
  34. package/src/maintenance.js +0 -27
  35. package/src/page-blocks.js +29 -8
  36. package/src/page-check.js +6 -1
  37. package/src/theme.js +13 -2
  38. package/static/edgepress/brand/edgepress-mark.svg +7 -0
  39. package/static/edgepress/brand/mascot.png +0 -0
  40. package/static/edgepress/brand/og-image.png +0 -0
  41. package/static/edgepress/brand/og-image.svg +46 -0
  42. package/static/edgepress/code-copy.js +55 -0
  43. package/static/edgepress/icons.svg +24 -0
  44. package/themes/atelier/assets/style.css +48 -1
  45. package/themes/atelier/layouts/partials/head.html +5 -0
  46. package/themes/atelier/layouts/partials/header.html +1 -1
  47. package/themes/default/assets/style.css +49 -1
  48. package/themes/default/layouts/partials/head.html +3 -0
  49. package/themes/default/layouts/partials/header.html +1 -1
  50. package/themes/signal/assets/style.css +48 -1
  51. package/themes/signal/layouts/partials/head.html +5 -0
  52. package/themes/signal/layouts/partials/header.html +1 -1
@@ -0,0 +1,55 @@
1
+ const copyLabels = document.documentElement.lang.toLowerCase().startsWith('zh')
2
+ ? { copy: '复制', copied: '已复制到剪贴板。', failed: '复制失败,请手动选择并复制代码。', label: '复制代码' }
3
+ : { copy: 'Copy', copied: 'Copied to clipboard.', failed: 'Copy failed. Select and copy the code manually.', label: 'Copy code' };
4
+
5
+ function fallbackCopy(value) {
6
+ const field = document.createElement('textarea');
7
+ field.value = value;
8
+ field.setAttribute('readonly', '');
9
+ field.tabIndex = -1;
10
+ field.setAttribute('aria-hidden', 'true');
11
+ field.style.position = 'fixed';
12
+ field.style.inset = '0 auto auto -10000px';
13
+ document.body.append(field);
14
+ field.select();
15
+ let copied = false;
16
+ try { copied = document.execCommand('copy'); } catch { /* Clipboard permissions may deny the fallback. */ }
17
+ field.remove();
18
+ return copied;
19
+ }
20
+
21
+ for (const pre of document.querySelectorAll('pre[data-copyable-code]')) {
22
+ if (pre.parentElement?.classList.contains('code-copy-block')) continue;
23
+ const wrapper = document.createElement('div');
24
+ wrapper.className = 'code-copy-block';
25
+ const toolbar = document.createElement('div');
26
+ toolbar.className = 'code-copy-toolbar';
27
+ const button = document.createElement('button');
28
+ button.className = 'code-copy-button';
29
+ button.type = 'button';
30
+ button.textContent = copyLabels.copy;
31
+ button.setAttribute('aria-label', copyLabels.label);
32
+ const status = document.createElement('span');
33
+ status.className = 'code-copy-status';
34
+ status.setAttribute('role', 'status');
35
+ status.setAttribute('aria-live', 'polite');
36
+ toolbar.append(button);
37
+ pre.before(wrapper);
38
+ wrapper.append(toolbar, pre, status);
39
+
40
+ button.addEventListener('click', async () => {
41
+ const code = pre.querySelector('code') || pre;
42
+ let copied = false;
43
+ try {
44
+ if (navigator.clipboard?.writeText) {
45
+ await navigator.clipboard.writeText(code.textContent || '');
46
+ copied = true;
47
+ } else {
48
+ copied = fallbackCopy(code.textContent || '');
49
+ }
50
+ } catch {
51
+ copied = fallbackCopy(code.textContent || '');
52
+ }
53
+ status.textContent = copied ? copyLabels.copied : copyLabels.failed;
54
+ });
55
+ }
@@ -0,0 +1,24 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg">
2
+ <symbol id="home" viewBox="0 0 24 24"><path d="m3 10 9-7 9 7v10a1 1 0 0 1-1 1h-6v-7h-4v7H4a1 1 0 0 1-1-1z"/><path d="M8 8h8"/></symbol>
3
+ <symbol id="book-open" viewBox="0 0 24 24"><path d="M12 7v14M12 8c-2.5-2-5.5-2-9-1v13c3.5-1 6.5-1 9 1M12 8c2.5-2 5.5-2 9-1v13c-3.5-1-6.5-1-9 1"/><path d="M6 11h3m6 0h3"/></symbol>
4
+ <symbol id="rocket" viewBox="0 0 24 24"><path d="M12 15 9 12c1-5 4-8 11-9 0 7-4 10-8 11Z"/><path d="m9 12-4 1-2 4 5-1m4-1 1 4 4 2-1-5"/><circle cx="15" cy="8" r="1.5"/><path d="M7 18c-1 2-3 3-4 3 0-2 1-4 3-5"/></symbol>
5
+ <symbol id="newspaper" viewBox="0 0 24 24"><path d="M5 4h15v15a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2Z"/><path d="M3 8h5v5H3m8-5h6m-6 4h6m-11 4h11m-11 3h7"/></symbol>
6
+ <symbol id="search" viewBox="0 0 24 24"><circle cx="10.8" cy="10.8" r="6.8"/><path d="m16 16 5 5"/></symbol>
7
+ <symbol id="shield-check" viewBox="0 0 24 24"><path d="M12 3 20 6v5c0 5-3.2 8.2-8 10-4.8-1.8-8-5-8-10V6z"/><path d="m8.5 12 2.3 2.3 4.8-5"/></symbol>
8
+ <symbol id="rss" viewBox="0 0 24 24"><circle cx="5" cy="19" r="1"/><path d="M4 11a9 9 0 0 1 9 9M4 5a15 15 0 0 1 15 15"/></symbol>
9
+ <symbol id="file-text" viewBox="0 0 24 24"><path d="M6 3h8l5 5v13H6a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Z"/><path d="M14 3v6h5m-10 4h6m-6 4h6"/></symbol>
10
+ <symbol id="layers" viewBox="0 0 24 24"><path d="m12 3 9 5-9 5-9-5z"/><path d="m3 12 9 5 9-5M3 16l9 5 9-5"/></symbol>
11
+ <symbol id="code" viewBox="0 0 24 24"><path d="m8 7-5 5 5 5m8-10 5 5-5 5m-3-12-2 14"/></symbol>
12
+ <symbol id="puzzle" viewBox="0 0 24 24"><path d="M4 4h5a2.5 2.5 0 1 1 5 0h6v6a2.5 2.5 0 1 0 0 5v5h-6a2.5 2.5 0 1 0-5 0H4v-6a2.5 2.5 0 1 1 0-5z"/></symbol>
13
+ <symbol id="plug" viewBox="0 0 24 24"><path d="M9 3v6m6-6v6m-9 0h12v3a6 6 0 0 1-6 6v3m0-9v6"/></symbol>
14
+ <symbol id="cloud" viewBox="0 0 24 24"><path d="M7 18a5 5 0 1 1 1-9.9A6 6 0 0 1 19 10a4 4 0 0 1 0 8z"/><path d="m9 14 3-3 3 3m-3-3v7"/></symbol>
15
+ <symbol id="palette" viewBox="0 0 24 24"><path d="M12 3a9 9 0 1 0 0 18h1.2a2.3 2.3 0 0 0 1.6-4c-.7-.7-.2-2 1-2H18a3 3 0 0 0 3-3c0-5-4-9-9-9Z"/><circle cx="7.5" cy="11" r="1"/><circle cx="10" cy="7.5" r="1"/><circle cx="15" cy="8" r="1"/></symbol>
16
+ <symbol id="globe" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a14 14 0 0 1 0 18m0-18a14 14 0 0 0 0 18"/></symbol>
17
+ <symbol id="help-circle" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M9.5 9a2.6 2.6 0 1 1 4.8 1.4c-.8 1-2.3 1.4-2.3 3m0 3h.01"/></symbol>
18
+ <symbol id="arrow-up-right" viewBox="0 0 24 24"><path d="M7 17 17 7M8 7h9v9"/></symbol>
19
+ <symbol id="check-circle" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m8 12 2.7 2.7L16.5 9"/></symbol>
20
+ <symbol id="layout-grid" viewBox="0 0 24 24"><rect x="3" y="3" width="8" height="8" rx="1.5"/><rect x="13" y="3" width="8" height="5" rx="1.5"/><rect x="13" y="10" width="8" height="11" rx="1.5"/><rect x="3" y="13" width="8" height="8" rx="1.5"/></symbol>
21
+ <symbol id="terminal" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="m7 9 3 3-3 3m6 0h4"/></symbol>
22
+ <symbol id="settings" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="m19.4 15 .1.1 1.1.9-1.1 2-1.4-.4a8 8 0 0 1-1.7 1l-.3 1.4h-2.2l-.3-1.4a8 8 0 0 1-1.7-1l-1.4.4-1.1-2 1.1-.9A8 8 0 0 1 8.5 14L7 13.7v-2.4l1.5-.3a8 8 0 0 1 .9-1.7l-.5-1.4 2-1.2 1 1.1a8 8 0 0 1 2 0l1-1.1 2 1.2-.5 1.4a8 8 0 0 1 .9 1.7l1.5.3v2.4l-1.5.3"/></symbol>
23
+ <symbol id="sparkles" viewBox="0 0 24 24"><path d="m12 3 1.4 5.6L19 10l-5.6 1.4L12 17l-1.4-5.6L5 10l5.6-1.4zM19 16l.7 2.3L22 19l-2.3.7L19 22l-.7-2.3L16 19l2.3-.7z"/></symbol>
24
+ </svg>
@@ -117,4 +117,51 @@ main,.page-builder,.page-builder-row,.page-builder-cell,.post,.post-content,.pos
117
117
  @media(max-width:620px){.local-search-controls{align-items:stretch;flex-direction:column}.local-search-controls button{min-height:44px}.post-content pre,.code-widget pre,.steps-widget pre{padding:12px}}
118
118
  .locale-nav select{max-width:min(100%,13rem);padding:7px 30px 7px 10px;border:1px solid var(--line);border-radius:8px;background:var(--paper);color:var(--ink);font:inherit;cursor:pointer}
119
119
  .locale-nav select:focus-visible{outline:3px solid #cb774d;outline-offset:3px}
120
- @media(max-width:620px){.locale-nav select{min-height:42px;max-width:100%}}
120
+ @media(max-width:620px){.locale-nav select{min-height:42px;max-width:100%}}
121
+
122
+ /* Article contents and code tools use theme styling and wrap on narrow screens. */
123
+ .post-toc{display:block;max-width:760px;margin:24px 0;padding:18px 22px;border:1px solid var(--line);border-radius:4px;background:var(--panel)}
124
+ .post-toc h2{margin:0 0 8px;font-size:1.05rem;letter-spacing:0}
125
+ .post-toc ol{margin:0;padding-inline-start:1.35rem}
126
+ .post-toc li{padding:2px 0}
127
+ .post-toc .post-toc-level-3{padding-inline-start:1rem}
128
+ .post-toc .post-toc-level-4,.post-toc .post-toc-level-5,.post-toc .post-toc-level-6{padding-inline-start:2rem}
129
+ .post-content h2[id],.post-content h3[id],.post-content h4[id],.post-content h5[id],.post-content h6[id]{scroll-margin-top:1rem}
130
+ .code-copy-block{max-width:100%;margin:1.25em 0;border:1px solid var(--line);border-radius:4px;overflow:hidden;background:#29271f}
131
+ .code-copy-block pre{margin:0;border-radius:0}
132
+ .code-copy-toolbar{display:flex;justify-content:flex-end;padding:7px 10px;background:var(--ink)}
133
+ .code-copy-button{min-height:36px;padding:5px 12px;border:1px solid currentColor;border-radius:3px;background:transparent;color:var(--paper);font:600 .88rem/1.3 ui-sans-serif,system-ui,sans-serif;cursor:pointer}
134
+ .code-copy-button:hover{background:var(--accent)}
135
+ .code-copy-button:focus-visible{outline:3px solid #32745b;outline-offset:2px}
136
+ .code-copy-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
137
+ .post-content pre,.code-widget pre,.steps-widget pre{max-width:100%;overflow-x:hidden;overflow-y:visible;white-space:pre-wrap;overflow-wrap:anywhere;word-break:normal;overscroll-behavior-inline:auto}
138
+ .post-content pre code,.code-widget pre code,.steps-widget pre code{white-space:inherit;overflow-wrap:inherit;word-break:inherit}
139
+ .pagination{flex-wrap:wrap;gap:12px}
140
+ @media(max-width:620px){.post-toc{padding:14px}.code-copy-button{min-height:44px}.post-content pre,.code-widget pre,.steps-widget pre{padding:12px}}
141
+
142
+ /* A contemporary studio palette: porcelain, berry, and apricot. */
143
+ :root{--paper:#fff8f4;--panel:#fffdfb;--ink:#30202e;--muted:#705b6b;--line:#ead7df;--accent:#a12f50;--warm:#a85a0b}
144
+ body{background:radial-gradient(ellipse at 88% 2%,#ffe5df 0,transparent 32%),var(--paper)}
145
+ .intro,.hero-block,.cta-block{background:linear-gradient(125deg,#fffdfb 0%,#ffebe4 100%)}
146
+ .page-section--soft,.error-page{background:#fff0ed}
147
+ .page-section--accent{background:#ffe8d1}
148
+ .page-section--dark{background:#352539}
149
+ .steps-widget pre,.code-widget pre,.code-copy-block{background:#30202e}
150
+ .table-widget th{background:#fae7e5}
151
+ .notice-widget{background:#fff0ed}
152
+ .notice-widget--warning{background:#fff0d7}
153
+ .notice-widget--success{background:#eaf5ec}
154
+ .code-copy-block pre{background:#30202e;color:#fff8f4}
155
+ .code-copy-button:focus-visible{outline-color:var(--warm)}
156
+
157
+ /* Shared EdgePress marks and SVG icons keep common navigation recognizable across themes. */
158
+ .brand{display:inline-flex;align-items:center;gap:10px}
159
+ .brand-mark{display:block;width:36px;height:36px;flex:0 0 auto;object-fit:contain}
160
+ .primary-navigation a,.site-header nav a,.footer-navigation a{display:inline-flex;align-items:center;gap:.42em}
161
+ .navigation-icon{display:block;width:1.05em;height:1.05em;flex:0 0 auto;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
162
+ .hero-aside{display:grid;align-content:center;justify-items:center;gap:16px;min-width:0}
163
+ .hero-mascot{display:block;width:min(100%,230px);height:auto;max-height:220px;object-fit:contain;filter:drop-shadow(0 9px 13px #315e4922)}
164
+ .hero-aside .hero-highlights{width:100%;align-self:stretch}
165
+ .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
+ .latest-posts-pagination{justify-content:flex-start;gap:16px;margin-top:18px}
167
+ .latest-posts-pagination a:last-child{margin-left:auto}
@@ -5,6 +5,8 @@
5
5
  <meta name="keywords" content="{{page.keywords}}">
6
6
  <meta name="author" content="{{site.seo.author}}">
7
7
  <title>{{page.title}}</title>
8
+ <meta name="theme-color" content="#315e49">
9
+ <link rel="icon" type="image/svg+xml" href="/edgepress/brand/edgepress-mark.svg">
8
10
  <link rel="canonical" href="{{page.canonical}}">
9
11
  <meta property="og:type" content="website">
10
12
  <meta property="og:title" content="{{page.title}}">
@@ -12,6 +14,9 @@
12
14
  <meta property="og:url" content="{{page.canonical}}">
13
15
  <meta property="og:image" content="{{page.image}}">
14
16
  <meta name="twitter:card" content="summary_large_image">
17
+ <meta name="twitter:title" content="{{page.title}}">
18
+ <meta name="twitter:description" content="{{page.description}}">
19
+ <meta name="twitter:image" content="{{page.image}}">
15
20
  <link rel="alternate" type="application/atom+xml" href="{{site.feedPath}}" title="{{site.feedLabel}}">
16
21
  <link rel="stylesheet" href="{{site.stylesheet}}">
17
22
  <script type="application/ld+json">{{{page.jsonLd}}}</script>
@@ -1,5 +1,5 @@
1
1
  <header class="site-header atelier-header {{site.headerClass}}">
2
- <a class="brand {{site.brandClass}}" href="{{site.homePath}}">{{site.headerBrand}}</a>
2
+ <a class="brand {{site.brandClass}}" href="{{site.homePath}}"><img class="brand-mark" src="/edgepress/brand/edgepress-mark.svg" alt="" aria-hidden="true" width="36" height="36">{{site.headerBrand}}</a>
3
3
  <nav class="primary-navigation {{site.primaryNavigationClass}}" aria-label="{{site.mainNavigationLabel}}">{{{site.primaryNavigationHtml}}}</nav>
4
4
  <div class="locale-nav {{site.languageNavigationClass}}" role="group" aria-label="{{site.languageLabel}}">{{{site.localeLinksHtml}}}</div>
5
5
  </header>
@@ -154,4 +154,52 @@ main,.page-builder,.page-builder-row,.page-builder-cell,.post,.post-content,.pos
154
154
  @media(max-width:620px){.local-search-controls{align-items:stretch;flex-direction:column}.local-search-controls button{min-height:44px}.post-content pre,.code-widget pre,.steps-widget pre{padding:12px}}
155
155
  .locale-nav select{max-width:min(100%,13rem);padding:7px 30px 7px 10px;border:1px solid var(--line);border-radius:8px;background:var(--paper);color:var(--ink);font:inherit;cursor:pointer}
156
156
  .locale-nav select:focus-visible{outline:3px solid #cb774d;outline-offset:3px}
157
- @media(max-width:620px){.locale-nav select{min-height:42px;max-width:100%}}
157
+ @media(max-width:620px){.locale-nav select{min-height:42px;max-width:100%}}
158
+
159
+ /* Article contents and code tools use theme styling and wrap on narrow screens. */
160
+ .post-toc{max-width:760px;margin:24px auto;padding:18px 22px;border:1px solid var(--line);border-radius:12px;background:var(--paper)}
161
+ .post-toc h2{margin:0 0 8px;font-size:1.05rem;letter-spacing:0}
162
+ .post-toc ol{margin:0;padding-inline-start:1.35rem}
163
+ .post-toc li{padding:2px 0}
164
+ .post-toc .post-toc-level-3{padding-inline-start:1rem}
165
+ .post-toc .post-toc-level-4,.post-toc .post-toc-level-5,.post-toc .post-toc-level-6{padding-inline-start:2rem}
166
+ .post-content h2[id],.post-content h3[id],.post-content h4[id],.post-content h5[id],.post-content h6[id]{scroll-margin-top:1rem}
167
+ .code-copy-block{max-width:100%;margin:1.25em 0;border-radius:10px;overflow:hidden;background:#edf0ea}
168
+ .code-copy-block pre{margin:0;border-radius:0}
169
+ .code-copy-toolbar{display:flex;justify-content:flex-end;padding:7px 10px;background:var(--ink)}
170
+ .code-copy-button{min-height:36px;padding:5px 12px;border:1px solid currentColor;border-radius:7px;background:transparent;color:var(--paper);font:600 .88rem/1.3 ui-sans-serif,system-ui,sans-serif;cursor:pointer}
171
+ .code-copy-button:hover{background:var(--accent)}
172
+ .code-copy-button:focus-visible{outline:3px solid #cb774d;outline-offset:2px}
173
+ .code-copy-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
174
+ .post-content pre,.code-widget pre,.steps-widget pre{max-width:100%;overflow-x:hidden;overflow-y:visible;white-space:pre-wrap;overflow-wrap:anywhere;word-break:normal;overscroll-behavior-inline:auto}
175
+ .post-content pre code,.code-widget pre code,.steps-widget pre code{white-space:inherit;overflow-wrap:inherit;word-break:inherit}
176
+ .pagination{flex-wrap:wrap;gap:12px}
177
+ @media(max-width:620px){.post-toc{padding:14px}.code-copy-button{min-height:44px}.post-content pre,.code-widget pre,.steps-widget pre{padding:12px}}
178
+
179
+ /* A sharper editorial palette: cobalt ink, lilac surfaces, and citrus highlights. */
180
+ :root{--paper:#f7f8ff;--panel:#fff;--ink:#171a35;--muted:#5e6480;--line:#dce0f2;--accent:#3945c6;--warm:#d94d3f}
181
+ body{background:radial-gradient(ellipse at 92% 0%,#e9e9ff 0,transparent 33%),var(--paper)}
182
+ .hero-block,.cta-block{background:linear-gradient(118deg,#e5e7ff 0%,#fff0dc 100%)}
183
+ .page-section--soft,.error-page{background:#f0f1ff}
184
+ .page-section--accent{background:#ffefd7}
185
+ .page-section--dark{background:#211d49}
186
+ .hero-highlights li{background:#ffffffd9;border-color:#ffffff}
187
+ .steps-widget pre,.code-widget pre,.code-copy-block{background:#211d49}
188
+ .table-widget th{background:#ededff}
189
+ .notice-widget{background:#f0f1ff}
190
+ .notice-widget--warning{background:#fff0dc}
191
+ .notice-widget--success{background:#e7f7ef}
192
+ .code-copy-block pre{background:#211d49;color:#f7f8ff}
193
+ .code-copy-button:focus-visible,.local-search-form :focus-visible{outline-color:var(--warm)}
194
+
195
+ /* Shared EdgePress marks and SVG icons keep common navigation recognizable across themes. */
196
+ .brand{display:inline-flex;align-items:center;gap:10px}
197
+ .brand-mark{display:block;width:36px;height:36px;flex:0 0 auto;object-fit:contain}
198
+ .primary-navigation a,.site-header nav a,.footer-navigation a{display:inline-flex;align-items:center;gap:.42em}
199
+ .navigation-icon{display:block;width:1.05em;height:1.05em;flex:0 0 auto;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
200
+ .hero-aside{display:grid;align-content:center;justify-items:center;gap:16px;min-width:0}
201
+ .hero-mascot{display:block;width:min(100%,230px);height:auto;max-height:220px;object-fit:contain;filter:drop-shadow(0 9px 13px #315e4922)}
202
+ .hero-aside .hero-highlights{width:100%;align-self:stretch}
203
+ .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
+ .latest-posts-pagination{justify-content:flex-start;gap:16px;margin-top:18px}
205
+ .latest-posts-pagination a:last-child{margin-left:auto}
@@ -5,6 +5,8 @@
5
5
  <meta name="keywords" content="{{page.keywords}}">
6
6
  <meta name="author" content="{{site.seo.author}}">
7
7
  <title>{{page.title}}</title>
8
+ <meta name="theme-color" content="#315e49">
9
+ <link rel="icon" type="image/svg+xml" href="/edgepress/brand/edgepress-mark.svg">
8
10
  <link rel="canonical" href="{{page.canonical}}">
9
11
  <meta property="og:type" content="website">
10
12
  <meta property="og:title" content="{{page.title}}">
@@ -14,6 +16,7 @@
14
16
  <meta name="twitter:card" content="summary_large_image">
15
17
  <meta name="twitter:title" content="{{page.title}}">
16
18
  <meta name="twitter:description" content="{{page.description}}">
19
+ <meta name="twitter:image" content="{{page.image}}">
17
20
  <link rel="alternate" type="application/atom+xml" href="{{site.feedPath}}" title="{{site.feedLabel}}">
18
21
  <link rel="stylesheet" href="{{site.stylesheet}}">
19
22
  <script type="application/ld+json">{{{page.jsonLd}}}</script>
@@ -1,5 +1,5 @@
1
1
  <header class="site-header {{site.headerClass}}">
2
- <a class="brand {{site.brandClass}}" href="{{site.homePath}}">{{site.headerBrand}}</a>
2
+ <a class="brand {{site.brandClass}}" href="{{site.homePath}}"><img class="brand-mark" src="/edgepress/brand/edgepress-mark.svg" alt="" aria-hidden="true" width="36" height="36">{{site.headerBrand}}</a>
3
3
  <nav class="primary-navigation {{site.primaryNavigationClass}}" aria-label="{{site.mainNavigationLabel}}">{{{site.primaryNavigationHtml}}}</nav>
4
4
  <div class="locale-nav {{site.languageNavigationClass}}" role="group" aria-label="{{site.languageLabel}}">{{{site.localeLinksHtml}}}</div>
5
5
  </header>
@@ -110,4 +110,51 @@ main,.page-builder,.page-builder-row,.page-builder-cell,.post,.post-content,.pos
110
110
  @media(max-width:620px){.local-search-controls{align-items:stretch;flex-direction:column}.local-search-controls button{min-height:44px}.post-content pre,.code-widget pre,.steps-widget pre{padding:12px}}
111
111
  .locale-nav select{max-width:min(100%,13rem);padding:7px 30px 7px 10px;border:1px solid var(--line);border-radius:8px;background:var(--paper);color:var(--ink);font:inherit;cursor:pointer}
112
112
  .locale-nav select:focus-visible{outline:3px solid #cb774d;outline-offset:3px}
113
- @media(max-width:620px){.locale-nav select{min-height:42px;max-width:100%}}
113
+ @media(max-width:620px){.locale-nav select{min-height:42px;max-width:100%}}
114
+
115
+ /* Article contents and code tools use theme styling and wrap on narrow screens. */
116
+ .post-toc{display:block;max-width:760px;margin:24px 0;padding:18px 22px;border:1px solid var(--line);border-radius:12px;background:var(--panel)}
117
+ .post-toc h2{margin:0 0 8px;font-size:1.05rem;letter-spacing:0}
118
+ .post-toc ol{margin:0;padding-inline-start:1.35rem}
119
+ .post-toc li{padding:2px 0}
120
+ .post-toc .post-toc-level-3{padding-inline-start:1rem}
121
+ .post-toc .post-toc-level-4,.post-toc .post-toc-level-5,.post-toc .post-toc-level-6{padding-inline-start:2rem}
122
+ .post-content h2[id],.post-content h3[id],.post-content h4[id],.post-content h5[id],.post-content h6[id]{scroll-margin-top:1rem}
123
+ .code-copy-block{max-width:100%;margin:1.25em 0;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:#20253a}
124
+ .code-copy-block pre{margin:0;border-radius:0}
125
+ .code-copy-toolbar{display:flex;justify-content:flex-end;padding:7px 10px;background:var(--ink)}
126
+ .code-copy-button{min-height:36px;padding:5px 12px;border:1px solid currentColor;border-radius:7px;background:transparent;color:var(--paper);font:600 .88rem/1.3 ui-sans-serif,system-ui,sans-serif;cursor:pointer}
127
+ .code-copy-button:hover{background:var(--accent)}
128
+ .code-copy-button:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
129
+ .code-copy-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
130
+ .post-content pre,.code-widget pre,.steps-widget pre{max-width:100%;overflow-x:hidden;overflow-y:visible;white-space:pre-wrap;overflow-wrap:anywhere;word-break:normal;overscroll-behavior-inline:auto}
131
+ .post-content pre code,.code-widget pre code,.steps-widget pre code{white-space:inherit;overflow-wrap:inherit;word-break:inherit}
132
+ .pagination{flex-wrap:wrap;gap:12px}
133
+ @media(max-width:620px){.post-toc{padding:14px}.code-copy-button{min-height:44px}.post-content pre,.code-widget pre,.steps-widget pre{padding:12px}}
134
+
135
+ /* A vivid night palette: ink blue, ultraviolet panels, and electric lime. */
136
+ :root{--night:#101426;--panel:#1d223a;--ink:#f2f4ff;--muted:#aeb5ce;--line:#363d5b;--accent:#b7f36b;--warm:#ff9873}
137
+ body{background:radial-gradient(ellipse at 14% 0%,#302052 0,transparent 38%),var(--night)}
138
+ .post-card,.hero-block,.cta-block,.error-page{background:linear-gradient(140deg,#28203f,#1a2035)}
139
+ .page-section--soft{background:#1d2740}
140
+ .page-section--accent{background:#292942}
141
+ .page-section--dark{background:#0b1020}
142
+ .steps-widget pre,.code-widget pre,.code-copy-block{background:#0b1020}
143
+ .table-widget th{background:#292d49}
144
+ .notice-widget--warning{background:#332a35}
145
+ .notice-widget--success{background:#1c342e}
146
+ .code-copy-block pre{background:#0b1020;color:#f2f4ff}
147
+ .local-search-controls button{color:var(--night)}
148
+ .code-copy-button:focus-visible{outline-color:var(--warm)}
149
+
150
+ /* Shared EdgePress marks and SVG icons keep common navigation recognizable across themes. */
151
+ .brand{display:inline-flex;align-items:center;gap:10px}
152
+ .brand-mark{display:block;width:36px;height:36px;flex:0 0 auto;object-fit:contain}
153
+ .primary-navigation a,.site-header nav a,.footer-navigation a{display:inline-flex;align-items:center;gap:.42em}
154
+ .navigation-icon{display:block;width:1.05em;height:1.05em;flex:0 0 auto;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
155
+ .hero-aside{display:grid;align-content:center;justify-items:center;gap:16px;min-width:0}
156
+ .hero-mascot{display:block;width:min(100%,230px);height:auto;max-height:220px;object-fit:contain;filter:drop-shadow(0 9px 13px #315e4922)}
157
+ .hero-aside .hero-highlights{width:100%;align-self:stretch}
158
+ .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
+ .latest-posts-pagination{justify-content:flex-start;gap:16px;margin-top:18px}
160
+ .latest-posts-pagination a:last-child{margin-left:auto}
@@ -5,6 +5,8 @@
5
5
  <meta name="keywords" content="{{page.keywords}}">
6
6
  <meta name="author" content="{{site.seo.author}}">
7
7
  <title>{{page.title}}</title>
8
+ <meta name="theme-color" content="#315e49">
9
+ <link rel="icon" type="image/svg+xml" href="/edgepress/brand/edgepress-mark.svg">
8
10
  <link rel="canonical" href="{{page.canonical}}">
9
11
  <meta property="og:type" content="website">
10
12
  <meta property="og:title" content="{{page.title}}">
@@ -12,6 +14,9 @@
12
14
  <meta property="og:url" content="{{page.canonical}}">
13
15
  <meta property="og:image" content="{{page.image}}">
14
16
  <meta name="twitter:card" content="summary_large_image">
17
+ <meta name="twitter:title" content="{{page.title}}">
18
+ <meta name="twitter:description" content="{{page.description}}">
19
+ <meta name="twitter:image" content="{{page.image}}">
15
20
  <link rel="alternate" type="application/atom+xml" href="{{site.feedPath}}" title="{{site.feedLabel}}">
16
21
  <link rel="stylesheet" href="{{site.stylesheet}}">
17
22
  <script type="application/ld+json">{{{page.jsonLd}}}</script>
@@ -1,5 +1,5 @@
1
1
  <header class="signal-header site-header {{site.headerClass}}">
2
- <a class="brand {{site.brandClass}}" href="{{site.homePath}}"><span class="signal-mark" aria-hidden="true"></span>{{site.headerBrand}}</a>
2
+ <a class="brand {{site.brandClass}}" href="{{site.homePath}}"><img class="brand-mark" src="/edgepress/brand/edgepress-mark.svg" alt="" aria-hidden="true" width="36" height="36">{{site.headerBrand}}</a>
3
3
  <nav class="primary-navigation {{site.primaryNavigationClass}}" aria-label="{{site.mainNavigationLabel}}">{{{site.primaryNavigationHtml}}}</nav>
4
4
  <div class="locale-nav {{site.languageNavigationClass}}" role="group" aria-label="{{site.languageLabel}}">{{{site.localeLinksHtml}}}</div>
5
5
  </header>