PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / trunk
Jetpack – WP Security, Backup, Speed, & Growth vtrunk
16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / _inc / lib / admin-pages / class-akismet-admin-chrome.php
jetpack / _inc / lib / admin-pages Last commit date
class-akismet-admin-chrome.php 1 week ago class-jetpack-about-page.php 2 months ago class-jetpack-ai-page.php 1 week ago class-jetpack-redux-state-helper.php 1 week ago class.jetpack-admin-page.php 4 weeks ago class.jetpack-landing-page.php 2 years ago class.jetpack-react-page.php 7 months ago class.jetpack-settings-page.php 4 weeks ago
class-akismet-admin-chrome.php
366 lines
1 <?php
2 /**
3 * Renders the unified Jetpack admin header and footer chrome on Akismet's admin pages.
4 *
5 * Akismet (5.7+) exposes two action hooks in its admin views:
6 * - `akismet_header`: when an action is registered, it REPLACES Akismet's default masthead.
7 * - `akismet_footer`: rendered at the bottom of every admin view; empty by default.
8 *
9 * This integration consumes those hooks from the Jetpack plugin so that Akismet's pages
10 * share the same branded header bar, standardized footer AND contained layout as the rest
11 * of the unified Jetpack admin (the `@wordpress/admin-ui` page header + `JetpackFooter` look
12 * used by My Jetpack, Protect, Social, etc.): a fixed header, an internally-scrolling middle
13 * and a footer pinned to the bottom of the viewport.
14 *
15 * The markup mirrors the admin-ui page header and `.jetpack-footer` component, and the
16 * styling is a small self-contained stylesheet (no external CSS, no JS, no build step) that
17 * reproduces the measured computed styles of those components plus the
18 * `jetpack-admin-page-layout` mixin, adapted to Akismet's markup
19 * (`#wpbody-content > #akismet-plugin-container > header / .akismet-lower / footer`). This
20 * keeps the integration resilient to the CSS-Module class hashing used by the real React
21 * components.
22 *
23 * NOTE: This class does not modify the Akismet plugin in any way. It only registers
24 * callbacks on Akismet's own action hooks.
25 *
26 * @package automattic/jetpack
27 */
28
29 use Automattic\Jetpack\Redirect;
30 use Automattic\Jetpack\Status;
31 use Automattic\Jetpack\Status\Host;
32
33 if ( ! defined( 'ABSPATH' ) ) {
34 exit( 0 );
35 }
36
37 /**
38 * Wires the unified Jetpack header, footer and contained layout onto Akismet's admin pages.
39 */
40 class Akismet_Admin_Chrome {
41
42 /**
43 * The green Jetpack logo mark, sized via the `height` attribute by callers.
44 *
45 * @param int $height Pixel height of the logo.
46 * @return string SVG markup.
47 */
48 private function jetpack_logo( $height ) {
49 return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" height="' . (int) $height . '" class="jp-akismet-logo" aria-hidden="true"><path fill="#069e08" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M15,19H7l8-16V19z M17,29V13h8L17,29z"></path></svg>';
50 }
51
52 /**
53 * The Akismet logo mark — the green rounded square with the white "A", taken from
54 * Akismet's own `akismet-refresh-logo.svg`. Sized via the `height` attribute by callers.
55 *
56 * @param int $height Pixel height of the logo.
57 * @return string SVG markup.
58 */
59 private function akismet_logo( $height ) {
60 return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44" height="' . (int) $height . '" class="jp-akismet-mark" aria-hidden="true"><rect width="44" height="44" fill="#357B49" rx="6"/><path fill="#fff" fill-rule="evenodd" d="m29.746 28.31-6.392-16.797c-.152-.397-.305-.672-.789-.675-.673 0-1.408.611-1.746 1.316l-7.378 16.154c-.072.16-.143.311-.214.454-.5.995-1.045 1.546-2.357 1.626a.399.399 0 0 0-.16.033l-.01.004a.399.399 0 0 0-.23.392v.01c0 .054.01.106.03.155l.004.01a.416.416 0 0 0 .394.252h6.212a.417.417 0 0 0 .307-.12.416.416 0 0 0 .124-.305.398.398 0 0 0-.105-.302.399.399 0 0 0-.294-.127c-.757 0-2.197-.062-2.197-1.164.02-.318.103-.63.245-.916l1.399-3.152c.52-1.163 1.654-1.163 2.572-1.163h5.843c.023 0 .044 0 .062.003.13.014.16.081.214.242l1.534 4.07a2.857 2.857 0 0 1 .216 1.04c0 .054-.003.104-.01.153-.09.726-.831.887-1.49.887a.4.4 0 0 0-.294.127l-.007.008-.007.008a.401.401 0 0 0-.092.286v.01c0 .054.01.106.03.155l.005.01a.42.42 0 0 0 .395.252h7.011a.413.413 0 0 0 .279-.13.412.412 0 0 0 .11-.297.387.387 0 0 0-.09-.294.388.388 0 0 0-.277-.135c-1.448-.122-2.295-.643-2.847-2.08Zm-11.985-5.844 2.847-6.304c.361-.728.659-1.486.889-2.265 0-.06.03-.092.06-.092s.061.032.061.091c.02.122.045.247.073.374.197.888.584 1.878.914 2.723l.176.453 1.684 4.529a.927.927 0 0 1 .092.4.473.473 0 0 1-.009.094c-.041.202-.228.272-.602.272h-6.063c-.122 0-.184-.03-.184-.092a.36.36 0 0 1 .062-.183Zm17.107-.721c0 .786-.446 1.231-1.25 1.231-.806 0-1.125-.409-1.125-1.034 0-.786.465-1.231 1.25-1.231.785 0 1.125.427 1.125 1.034ZM9.629 23.002c.803 0 1.25-.447 1.25-1.231 0-.607-.343-1.036-1.128-1.036-.785 0-1.25.447-1.25 1.231 0 .625.325 1.036 1.128 1.036Z" clip-rule="evenodd"/></svg>';
61 }
62
63 /**
64 * Register the hooks that drive the chrome.
65 *
66 * Safe to call unconditionally: the header/footer callbacks are only ever fired by
67 * Akismet's own admin views, and the inline stylesheet is printed alongside the header.
68 *
69 * Idempotent: this can be wired from more than one place depending on the platform —
70 * `Jetpack_Admin` on Atomic/self-hosted, and `Akismet_Admin_WPCOM` on WordPress.com
71 * Simple sites (the two run under different load orders). The static guard ensures the
72 * `akismet_header` / `akismet_footer` callbacks are only ever registered once, so the
73 * chrome can never render twice regardless of how many call sites fire.
74 */
75 public function init_hooks() {
76 static $registered = false;
77 if ( $registered ) {
78 return;
79 }
80 $registered = true;
81
82 add_action( 'akismet_header', array( $this, 'render_header' ) );
83 add_action( 'akismet_footer', array( $this, 'render_footer' ) );
84 }
85
86 /**
87 * The self-contained stylesheet reproducing the admin-ui page header + `.jetpack-footer`
88 * computed styles. Printed once, alongside the header.
89 */
90 private function print_styles() {
91 static $printed = false;
92 if ( $printed ) {
93 return;
94 }
95 $printed = true;
96 ?>
97 <style id="jp-akismet-chrome-css">
98 /* ── Header (admin-ui page header look) ── */
99 .jp-akismet-header {
100 display: flex;
101 align-items: center;
102 box-sizing: border-box;
103 min-height: 72px;
104 padding: 16px 24px;
105 background: #fff;
106 /* `box-shadow` (not `border-bottom`) so the hairline never adds to the
107 box and nudges the logo/title off the admin-ui header's vertical center. */
108 box-shadow: inset 0 -1px 0 #e4e4e4;
109 }
110 .jp-akismet-header__title {
111 display: flex;
112 align-items: center;
113 gap: 8px;
114 text-decoration: none;
115 }
116 /* Keep the ring to keyboard focus. Scoped to the container to outrank
117 wp-admin's `a:focus` and Akismet's `#akismet-plugin-container
118 a:focus-visible`, which both beat a bare class selector. */
119 #akismet-plugin-container .jp-akismet-header__title:focus:not( :focus-visible ) {
120 box-shadow: none;
121 outline: none;
122 }
123 #akismet-plugin-container .jp-akismet-header__title:focus-visible {
124 border-radius: 2px;
125 box-shadow: 0 0 0 2px #2271b1;
126 outline: 2px solid transparent;
127 }
128 /* 24×24 visual slot centering the 20px logo, matching My Jetpack/Boost. */
129 .jp-akismet-header__visual {
130 display: flex;
131 align-items: center;
132 justify-content: center;
133 flex-shrink: 0;
134 width: 24px;
135 height: 24px;
136 }
137 .jp-akismet-header__title h1 {
138 margin: 0;
139 padding: 0;
140 font-size: 15px;
141 font-weight: 500;
142 line-height: 20px;
143 color: #1e1e1e;
144 }
145 /* ── Footer (.jetpack-footer look) ── */
146 .jp-akismet-footer {
147 display: flex;
148 align-items: center;
149 flex-wrap: wrap;
150 gap: 24px;
151 box-sizing: border-box;
152 padding: 20px 24px;
153 border-top: 1px solid #e4e4e4;
154 background: #fff;
155 color: #1e1e1e;
156 font-size: 13px;
157 }
158 .jp-akismet-footer__logo {
159 display: flex;
160 align-items: center;
161 gap: 8px;
162 font-weight: 500;
163 }
164 .jp-akismet-footer__menu {
165 display: flex;
166 gap: 16px;
167 }
168 /* `#akismet-plugin-container a` is green in Akismet's own CSS; this scoped
169 selector outranks it so the footer links read as neutral grey (#707070,
170 matching My Jetpack's footer links). */
171 #akismet-plugin-container .jp-akismet-footer__menu a {
172 color: #707070;
173 text-decoration: none;
174 }
175 #akismet-plugin-container .jp-akismet-footer__menu a:hover {
176 color: #1e1e1e;
177 text-decoration: underline;
178 }
179 .jp-akismet-footer__a8c {
180 margin-inline-start: auto;
181 display: inline-flex;
182 align-items: center;
183 }
184 /* Mobile: the byline drops its right-push and wraps to its own full-width
185 row, left-aligned — matching how JetpackFooter stacks on other pages. */
186 @media (max-width: 782px) {
187 .jp-akismet-footer__a8c {
188 margin-inline-start: 0;
189 flex-basis: 100%;
190 }
191 }
192 .jp-akismet-footer__a8c svg path {
193 fill: #707070;
194 }
195
196 /* ── Hello Dolly ──
197 The `.jetpack-admin-page #dolly` treatment (right-aligned, italic,
198 WPDS colors) ships in the jetpack-components / My Jetpack admin CSS,
199 which doesn't load on Akismet's page — so without this, Dolly's lyric
200 falls back to left-aligned here. Re-declare it so Dolly lands top-right
201 exactly like every other unified Jetpack admin page. */
202 .jetpack-admin-page #dolly {
203 float: none;
204 text-align: end;
205 background: var(--wpds-color-background-surface-neutral-strong, #fff);
206 font-style: italic;
207 color: var(--wpds-color-foreground-content-neutral-weak, #87a6bc);
208 border-bottom: none;
209 }
210 @media (max-width: 659px) {
211 .jetpack-admin-page #dolly {
212 display: none;
213 }
214 }
215
216 /* ── Contained layout: fixed header, scrolling middle, pinned footer ──
217 Mirrors the jetpack-admin-page-layout mixin, adapted to Akismet's
218 markup (#wpbody-content > #akismet-plugin-container > header/.akismet-lower/footer).
219 Scoped to both menu locations: jetpack_page_… and settings_page_…
220
221 The mixin uses physical `left`/`right` because its SCSS is compiled
222 through rtlcss, which emits a flipped stylesheet. This inline `<style>`
223 has no such build step, so it uses CSS logical properties
224 (`inset-inline-*`, `padding-inline-*`, `margin-inline`) to flip with the
225 admin menu under RTL locales. */
226 body[class*="_page_akismet-key-config"] #wpcontent {
227 padding-inline-start: 0;
228 }
229 body[class*="_page_akismet-key-config"] #wpfooter {
230 display: none;
231 }
232 /* `#screen-meta-links` (the Screen Options / Help tabs container) is always
233 emitted by core's admin header even when empty, and core gives it
234 `margin: 0 10px 20px 0`. On wp.com Simple sites its contents are hidden
235 but the element — and its 20px bottom margin — remain, reserving a blank
236 slot at the very top of the page above the Jetpack header. The
237 `jetpack-admin-page-layout` mixin hides it for the same reason; do it here
238 too. Left UNSCOPED (not under `_page_akismet-key-config`) on purpose: the
239 inline stylesheet is only ever printed on Akismet admin views, and Simple
240 renders its stats UI under a different slug (`dashboard_page_akismet-stats`),
241 so an unscoped rule covers every page this chrome appears on. */
242 #screen-meta-links {
243 display: none;
244 }
245 body[class*="_page_akismet-key-config"] #wpbody-content {
246 box-sizing: border-box;
247 position: fixed;
248 top: var(--wp-admin-bar-height, 32px);
249 inset-inline-start: 160px;
250 inset-inline-end: 0;
251 bottom: 0;
252 width: auto;
253 padding-bottom: 0;
254 overflow: hidden;
255 display: flex;
256 flex-direction: column;
257 }
258 body[class*="_page_akismet-key-config"].folded #wpbody-content {
259 inset-inline-start: 36px;
260 }
261 @media (max-width: 960px) {
262 body[class*="_page_akismet-key-config"].auto-fold #wpbody-content {
263 inset-inline-start: 36px;
264 }
265 }
266 @media (min-width: 961px) {
267 body[class*="_page_akismet-key-config"].is-nav-unification:not(.folded) #wpbody-content {
268 inset-inline-start: 272px;
269 }
270 }
271 body[class*="_page_akismet-key-config"] #akismet-plugin-container {
272 flex: 1 1 auto;
273 min-height: 0;
274 min-width: 0;
275 display: flex;
276 flex-direction: column;
277 /* Drop Akismet's 1px container border: it insets the whole column by 1px,
278 pushing the header logo/title off the admin-ui alignment grid. */
279 border: 0;
280 }
281 body[class*="_page_akismet-key-config"] .jp-akismet-header {
282 flex-shrink: 0;
283 }
284 /* The scrollable middle. Target the generic child between header and
285 footer (not `.akismet-lower` specifically) so the config, start AND
286 stats (bare iframe) views all get a full-width scroll surface. The
287 `#wpbody-content` id keeps these rules ahead of Akismet's own
288 `.akismet-lower { width: 720px }`. */
289 body[class*="_page_akismet-key-config"] #wpbody-content > #akismet-plugin-container > :not(.jp-akismet-header):not(.jp-akismet-footer) {
290 flex: 1 1 auto;
291 min-height: 0;
292 min-width: 0;
293 width: auto;
294 max-width: none;
295 margin: 0;
296 overflow: auto;
297 }
298 /* Move the readable-width restriction onto the content blocks so the
299 scroll surface itself spans the full width (scrolling works wherever
300 the pointer is), while the cards stay a comfortable column, left-
301 aligned with the header. 45rem ≈ Akismet's original 720px column. */
302 body[class*="_page_akismet-key-config"] .akismet-lower > * {
303 box-sizing: border-box;
304 max-width: 45rem;
305 margin-inline: auto;
306 }
307 body[class*="_page_akismet-key-config"] .jp-akismet-footer {
308 flex-shrink: 0;
309 }
310 @media (max-width: 782px) {
311 body[class*="_page_akismet-key-config"] #wpbody-content,
312 body[class*="_page_akismet-key-config"].folded #wpbody-content,
313 body[class*="_page_akismet-key-config"].auto-fold #wpbody-content {
314 top: var(--wp-admin-bar-height, 46px);
315 inset-inline-start: 0;
316 }
317 }
318 </style>
319 <?php
320 }
321
322 /**
323 * Render the admin-ui-style header (Akismet logo + title) that replaces Akismet's default masthead.
324 */
325 public function render_header() {
326 $this->print_styles();
327 ?>
328 <header class="jp-akismet-header">
329 <a class="jp-akismet-header__title" href="<?php echo esc_url( admin_url( 'admin.php?page=akismet-key-config' ) ); ?>">
330 <span class="jp-akismet-header__visual" aria-hidden="true"><?php echo $this->akismet_logo( 20 ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static SVG. ?></span>
331 <h1><?php esc_html_e( 'Akismet Anti-spam', 'jetpack' ); ?></h1>
332 </a>
333 </header>
334 <?php
335 }
336
337 /**
338 * Render the unified Jetpack footer (`.jetpack-footer` look) at the bottom of the page.
339 */
340 public function render_footer() {
341 // Match wrap_ui(): link the byline to the local About page when Jetpack isn't connectable,
342 // otherwise to the external jetpack.com redirect.
343 $connectable = ! Jetpack::is_connection_ready() && ! ( new Status() )->is_offline_mode();
344 $a8c_url = ! $connectable
345 ? admin_url( 'admin.php?page=jetpack_about' )
346 : Redirect::get_url( 'jetpack' );
347 ?>
348 <footer class="jp-akismet-footer jetpack-footer" aria-label="<?php esc_attr_e( 'Jetpack', 'jetpack' ); ?>" role="contentinfo">
349 <div class="jp-akismet-footer__logo">
350 <?php echo $this->jetpack_logo( 16 ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static SVG. ?>
351 <span><?php esc_html_e( 'Jetpack', 'jetpack' ); ?></span>
352 </div>
353 <?php if ( ! ( new Host() )->is_wpcom_platform() ) : ?>
354 <nav class="jp-akismet-footer__menu">
355 <a href="<?php echo esc_url( admin_url( 'admin.php?page=my-jetpack#/products' ) ); ?>"><?php echo esc_html_x( 'Products', 'Navigation item', 'jetpack' ); ?></a>
356 <a href="<?php echo esc_url( admin_url( 'admin.php?page=my-jetpack#/help' ) ); ?>"><?php echo esc_html_x( 'Help', 'Navigation item', 'jetpack' ); ?></a>
357 </nav>
358 <?php endif; ?>
359 <a class="jp-akismet-footer__a8c" href="<?php echo esc_url( $a8c_url ); ?>" aria-label="<?php esc_attr_e( 'An Automattic Airline', 'jetpack' ); ?>">
360 <svg role="img" x="0" y="0" viewBox="0 0 935 38.2" height="7" aria-hidden="true"><path d="M317.1 38.2c-12.6 0-20.7-9.1-20.7-18.5v-1.2c0-9.6 8.2-18.5 20.7-18.5 12.6 0 20.8 8.9 20.8 18.5v1.2C337.9 29.1 329.7 38.2 317.1 38.2zM331.2 18.6c0-6.9-5-13-14.1-13s-14 6.1-14 13v0.9c0 6.9 5 13.1 14 13.1s14.1-6.2 14.1-13.1V18.6zM175 36.8l-4.7-8.8h-20.9l-4.5 8.8h-7L157 1.3h5.5L182 36.8H175zM159.7 8.2L152 23.1h15.7L159.7 8.2zM212.4 38.2c-12.7 0-18.7-6.9-18.7-16.2V1.3h6.6v20.9c0 6.6 4.3 10.5 12.5 10.5 8.4 0 11.9-3.9 11.9-10.5V1.3h6.7V22C231.4 30.8 225.8 38.2 212.4 38.2zM268.6 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H268.6zM397.3 36.8V8.7l-1.8 3.1 -14.9 25h-3.3l-14.7-25 -1.8-3.1v28.1h-6.5V1.3h9.2l14 24.4 1.7 3 1.7-3 13.9-24.4h9.1v35.5H397.3zM454.4 36.8l-4.7-8.8h-20.9l-4.5 8.8h-7l19.2-35.5h5.5l19.5 35.5H454.4zM439.1 8.2l-7.7 14.9h15.7L439.1 8.2zM488.4 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H488.4zM537.3 6.8v30h-6.7v-30h-15.5V1.3h37.7v5.5H537.3zM569.3 36.8V4.6c2.7 0 3.7-1.4 3.7-3.4h2.8v35.5L569.3 36.8 569.3 36.8zM628 11.3c-3.2-2.9-7.9-5.7-14.2-5.7 -9.5 0-14.8 6.5-14.8 13.3v0.7c0 6.7 5.4 13 15.3 13 5.9 0 10.8-2.8 13.9-5.7l4 4.2c-3.9 3.8-10.5 7.1-18.3 7.1 -13.4 0-21.6-8.7-21.6-18.3v-1.2c0-9.6 8.9-18.7 21.9-18.7 7.5 0 14.3 3.1 18 7.1L628 11.3zM321.5 12.4c1.2 0.8 1.5 2.4 0.8 3.6l-6.1 9.4c-0.8 1.2-2.4 1.6-3.6 0.8l0 0c-1.2-0.8-1.5-2.4-0.8-3.6l6.1-9.4C318.7 11.9 320.3 11.6 321.5 12.4L321.5 12.4z"></path><path d="M37.5 36.7l-4.7-8.9H11.7l-4.6 8.9H0L19.4 0.8H25l19.7 35.9H37.5zM22 7.8l-7.8 15.1h15.9L22 7.8zM82.8 36.7l-23.3-24 -2.3-2.5v26.6h-6.7v-36H57l22.6 24 2.3 2.6V0.8h6.7v35.9H82.8z"></path><path d="M719.9 37l-4.8-8.9H694l-4.6 8.9h-7.1l19.5-36h5.6l19.8 36H719.9zM704.4 8l-7.8 15.1h15.9L704.4 8zM733 37V1h6.8v36H733zM781 37c-1.8 0-2.6-2.5-2.9-5.8l-0.2-3.7c-0.2-3.6-1.7-5.1-8.4-5.1h-12.8V37H750V1h19.6c10.8 0 15.7 4.3 15.7 9.9 0 3.9-2 7.7-9 9 7 0.5 8.5 3.7 8.6 7.9l0.1 3c0.1 2.5 0.5 4.3 2.2 6.1V37H781zM778.5 11.8c0-2.6-2.1-5.1-7.9-5.1h-13.8v10.8h14.4c5 0 7.3-2.4 7.3-5.2V11.8zM794.8 37V1h6.8v30.4h28.2V37H794.8zM836.7 37V1h6.8v36H836.7zM886.2 37l-23.4-24.1 -2.3-2.5V37h-6.8V1h6.5l22.7 24.1 2.3 2.6V1h6.8v36H886.2zM902.3 37V1H935v5.6h-26v9.2h20v5.5h-20v10.1h26V37H902.3z"></path></svg>
361 </a>
362 </footer>
363 <?php
364 }
365 }
366