From 8c40b0a95e80bf87fc80aafecd745e9802385a2e Mon Sep 17 00:00:00 2001 From: Jason Buckner Date: Thu, 10 Sep 2026 11:21:08 -0700 Subject: [PATCH 1/8] WEBDEV-9038: Migrate the topnav into elements Ports ia-topnav out of the iaux monorepo as ia-topnav, with every sub-element namespaced ia-topnav-* so it can't collide with the copies petabox and offshoot still load. element-names.test.ts holds that line: it checks the new names register and that all 17 generic names the old package claims stay free, since both packages load during the migration and a duplicate define throws rather than degrading. Ported from the WEBDEV-9036 branch rather than iaux master, so the uploader and biblio admin sections are here from the start. That PR touches most of what this move carries, so porting master would have meant doing the same work twice. No dependencies added, two dropped. ia-wayback-search only supplied a base class, and importing it registered the generic ia-wayback-search tag as a side effect, so it's one flattened element now. ia-styles only supplied the sr-only block, which is now a shared style in themes. Per-component style modules became inline styles, which is what every other element here does. The shared subnav fragment keeps a plain name at the component root. The user menu and signed-out dropdown returned exactly the base class's styles, and Lit already inherits those, so the overrides are gone. Three things dropped as dead: the ia-icon element, which nothing imported or rendered and which squatted a generic name; a write-only state field on the login button; and the redundant style overrides above. Two bugs came out of the move. Two tests had every assertion commented out, so they passed while checking nothing; both are rewritten against real behavior, taking the component from 52 tests to 94. And the wayback search's desktop icon read a variable nothing sets, with no fallback, so its fill resolved to invalid and painted black against the dark nav. It follows the topnav's own icon color now. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JpyQxVSkZFrWxxGamCcNhY --- ...b84ccced5d0f90dee41023cd32a38de3fa308d.png | Bin 0 -> 78063 bytes .../ia-topnav/assets/img/icon-audio.ts | 28 + .../ia-topnav/assets/img/icon-close.ts | 20 + .../assets/img/icon-donate-unpadded.ts | 19 + .../ia-topnav/assets/img/icon-donate.ts | 18 + .../ia-topnav/assets/img/icon-ellipses.ts | 19 + .../ia-topnav/assets/img/icon-ia-logo.ts | 30 + .../ia-topnav/assets/img/icon-images.ts | 19 + .../ia-topnav/assets/img/icon-search.ts | 19 + .../ia-topnav/assets/img/icon-software.ts | 18 + .../ia-topnav/assets/img/icon-texts.ts | 18 + .../assets/img/icon-upload-unpadded.ts | 18 + .../ia-topnav/assets/img/icon-upload.ts | 21 + .../ia-topnav/assets/img/icon-user.ts | 19 + .../ia-topnav/assets/img/icon-video.ts | 19 + src/elements/ia-topnav/assets/img/icon-web.ts | 19 + src/elements/ia-topnav/assets/img/icon.ts | 8 + src/elements/ia-topnav/assets/img/icons.ts | 33 + .../ia-topnav/assets/img/wayback-logo.ts | 21 + .../ia-topnav/assets/img/wordmark-stacked.ts | 13 + src/elements/ia-topnav/data/menus.test.ts | 57 ++ src/elements/ia-topnav/data/menus.ts | 691 ++++++++++++++++++ src/elements/ia-topnav/dropdown-menu.test.ts | 25 + src/elements/ia-topnav/dropdown-menu.ts | 322 ++++++++ src/elements/ia-topnav/element-names.test.ts | 81 ++ .../ia-topnav/ia-topnav-desktop-subnav.ts | 87 +++ .../ia-topnav-icon-hamburger.test.ts | 20 + .../ia-topnav/ia-topnav-icon-hamburger.ts | 49 ++ .../ia-topnav/ia-topnav-login-button.test.ts | 21 + .../ia-topnav/ia-topnav-login-button.ts | 176 +++++ .../ia-topnav/ia-topnav-media-button.test.ts | 23 + .../ia-topnav/ia-topnav-media-button.ts | 259 +++++++ .../ia-topnav/ia-topnav-media-menu.test.ts | 44 ++ .../ia-topnav/ia-topnav-media-menu.ts | 209 ++++++ .../ia-topnav/ia-topnav-media-slider.test.ts | 65 ++ .../ia-topnav/ia-topnav-media-slider.ts | 216 ++++++ .../ia-topnav/ia-topnav-media-subnav.ts | 294 ++++++++ .../ia-topnav/ia-topnav-more-slider.test.ts | 23 + .../ia-topnav/ia-topnav-more-slider.ts | 57 ++ .../ia-topnav/ia-topnav-primary-nav.test.ts | 136 ++++ .../ia-topnav/ia-topnav-primary-nav.ts | 662 +++++++++++++++++ .../ia-topnav-save-page-form.test.ts | 47 ++ .../ia-topnav/ia-topnav-save-page-form.ts | 121 +++ .../ia-topnav-signed-out-dropdown.ts | 5 + src/elements/ia-topnav/ia-topnav-story.ts | 156 ++++ .../ia-topnav/ia-topnav-user-menu.test.ts | 38 + src/elements/ia-topnav/ia-topnav-user-menu.ts | 26 + .../ia-topnav/ia-topnav-wayback-search.ts | 273 +++++++ .../ia-topnav-wayback-slider.test.ts | 99 +++ .../ia-topnav/ia-topnav-wayback-slider.ts | 125 ++++ src/elements/ia-topnav/ia-topnav.test.ts | 393 ++++++++++ src/elements/ia-topnav/ia-topnav.ts | 451 ++++++++++++ src/elements/ia-topnav/lib/format-url.ts | 2 + .../ia-topnav/lib/keyboard-navigation.ts | 171 +++++ .../ia-topnav/lib/make-boolean-string.ts | 12 + src/elements/ia-topnav/lib/query-handler.ts | 7 + src/elements/ia-topnav/lib/t-sentence-case.ts | 10 + src/elements/ia-topnav/models.ts | 70 ++ src/elements/ia-topnav/subnav-list-styles.ts | 49 ++ src/elements/ia-topnav/tracked-element.ts | 32 + src/elements/index.ts | 2 + src/themes/sr-only-styles.ts | 24 + 62 files changed, 6009 insertions(+) create mode 100644 .vitest-attachments/82b84ccced5d0f90dee41023cd32a38de3fa308d.png create mode 100644 src/elements/ia-topnav/assets/img/icon-audio.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-close.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-donate-unpadded.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-donate.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-ellipses.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-ia-logo.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-images.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-search.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-software.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-texts.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-upload-unpadded.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-upload.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-user.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-video.ts create mode 100644 src/elements/ia-topnav/assets/img/icon-web.ts create mode 100644 src/elements/ia-topnav/assets/img/icon.ts create mode 100644 src/elements/ia-topnav/assets/img/icons.ts create mode 100644 src/elements/ia-topnav/assets/img/wayback-logo.ts create mode 100644 src/elements/ia-topnav/assets/img/wordmark-stacked.ts create mode 100644 src/elements/ia-topnav/data/menus.test.ts create mode 100644 src/elements/ia-topnav/data/menus.ts create mode 100644 src/elements/ia-topnav/dropdown-menu.test.ts create mode 100644 src/elements/ia-topnav/dropdown-menu.ts create mode 100644 src/elements/ia-topnav/element-names.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-desktop-subnav.ts create mode 100644 src/elements/ia-topnav/ia-topnav-icon-hamburger.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-icon-hamburger.ts create mode 100644 src/elements/ia-topnav/ia-topnav-login-button.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-login-button.ts create mode 100644 src/elements/ia-topnav/ia-topnav-media-button.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-media-button.ts create mode 100644 src/elements/ia-topnav/ia-topnav-media-menu.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-media-menu.ts create mode 100644 src/elements/ia-topnav/ia-topnav-media-slider.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-media-slider.ts create mode 100644 src/elements/ia-topnav/ia-topnav-media-subnav.ts create mode 100644 src/elements/ia-topnav/ia-topnav-more-slider.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-more-slider.ts create mode 100644 src/elements/ia-topnav/ia-topnav-primary-nav.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-primary-nav.ts create mode 100644 src/elements/ia-topnav/ia-topnav-save-page-form.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-save-page-form.ts create mode 100644 src/elements/ia-topnav/ia-topnav-signed-out-dropdown.ts create mode 100644 src/elements/ia-topnav/ia-topnav-story.ts create mode 100644 src/elements/ia-topnav/ia-topnav-user-menu.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-user-menu.ts create mode 100644 src/elements/ia-topnav/ia-topnav-wayback-search.ts create mode 100644 src/elements/ia-topnav/ia-topnav-wayback-slider.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav-wayback-slider.ts create mode 100644 src/elements/ia-topnav/ia-topnav.test.ts create mode 100644 src/elements/ia-topnav/ia-topnav.ts create mode 100644 src/elements/ia-topnav/lib/format-url.ts create mode 100644 src/elements/ia-topnav/lib/keyboard-navigation.ts create mode 100644 src/elements/ia-topnav/lib/make-boolean-string.ts create mode 100644 src/elements/ia-topnav/lib/query-handler.ts create mode 100644 src/elements/ia-topnav/lib/t-sentence-case.ts create mode 100644 src/elements/ia-topnav/models.ts create mode 100644 src/elements/ia-topnav/subnav-list-styles.ts create mode 100644 src/elements/ia-topnav/tracked-element.ts create mode 100644 src/themes/sr-only-styles.ts diff --git a/.vitest-attachments/82b84ccced5d0f90dee41023cd32a38de3fa308d.png b/.vitest-attachments/82b84ccced5d0f90dee41023cd32a38de3fa308d.png new file mode 100644 index 0000000000000000000000000000000000000000..32ce38d77cf649e7717ba009ed5984ddfc187573 GIT binary patch literal 78063 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�@A5N5^u<3$fJ!4 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

A)JwtD$QR!a?#B>u<@ZBe432 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 eMA++kd>o + Audio icon + An illustration of an audio speaker. + + + + + + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-close.ts b/src/elements/ia-topnav/assets/img/icon-close.ts new file mode 100644 index 00000000..60dab359 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-close.ts @@ -0,0 +1,20 @@ +import { html } from 'lit'; + +export default html` + + Close icon + A line drawing of an X + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-donate-unpadded.ts b/src/elements/ia-topnav/assets/img/icon-donate-unpadded.ts new file mode 100644 index 00000000..8e1b0429 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-donate-unpadded.ts @@ -0,0 +1,19 @@ +import { html } from 'lit'; + +export default html` + + Donate icon + An illustration of a heart shape + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-donate.ts b/src/elements/ia-topnav/assets/img/icon-donate.ts new file mode 100644 index 00000000..e7f2c1b0 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-donate.ts @@ -0,0 +1,18 @@ +import { html } from 'lit'; + +export default html` + + Donate icon + An illustration of a heart shape + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-ellipses.ts b/src/elements/ia-topnav/assets/img/icon-ellipses.ts new file mode 100644 index 00000000..191e71c7 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-ellipses.ts @@ -0,0 +1,19 @@ +import { html } from 'lit'; + +export default html` + + Ellipses icon + An illustration of text ellipses. + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-ia-logo.ts b/src/elements/ia-topnav/assets/img/icon-ia-logo.ts new file mode 100644 index 00000000..ccacaced --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-ia-logo.ts @@ -0,0 +1,30 @@ +import { html } from 'lit'; + +export default html` + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-images.ts b/src/elements/ia-topnav/assets/img/icon-images.ts new file mode 100644 index 00000000..64e86d23 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-images.ts @@ -0,0 +1,19 @@ +import { html } from 'lit'; + +export default html` + + Images icon + An illustration of two photographs. + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-search.ts b/src/elements/ia-topnav/assets/img/icon-search.ts new file mode 100644 index 00000000..18eb1fc8 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-search.ts @@ -0,0 +1,19 @@ +import { html } from 'lit'; + +export default html` + + Search icon + An illustration of a magnifying glass. + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-software.ts b/src/elements/ia-topnav/assets/img/icon-software.ts new file mode 100644 index 00000000..6f9eed38 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-software.ts @@ -0,0 +1,18 @@ +import { html } from 'lit'; + +export default html` + + Software icon + An illustration of a 3.5" floppy disk. + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-texts.ts b/src/elements/ia-topnav/assets/img/icon-texts.ts new file mode 100644 index 00000000..e1796245 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-texts.ts @@ -0,0 +1,18 @@ +import { html } from 'lit'; + +export default html` + + Texts icon + An illustration of an open book. + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-upload-unpadded.ts b/src/elements/ia-topnav/assets/img/icon-upload-unpadded.ts new file mode 100644 index 00000000..5b80855a --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-upload-unpadded.ts @@ -0,0 +1,18 @@ +import { html } from 'lit'; + +export default html` + + Upload files + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-upload.ts b/src/elements/ia-topnav/assets/img/icon-upload.ts new file mode 100644 index 00000000..bdc6bfd6 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-upload.ts @@ -0,0 +1,21 @@ +import { html } from 'lit'; + +export default html` + + Upload icon + + An illustration of a horizontal line over an up pointing arrow. + + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-user.ts b/src/elements/ia-topnav/assets/img/icon-user.ts new file mode 100644 index 00000000..2d4a16b5 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-user.ts @@ -0,0 +1,19 @@ +import { html } from 'lit'; + +export default html` + + User icon + An illustration of a person's head and chest. + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-video.ts b/src/elements/ia-topnav/assets/img/icon-video.ts new file mode 100644 index 00000000..27385fa2 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-video.ts @@ -0,0 +1,19 @@ +import { html } from 'lit'; + +export default html` + + Video icon + An illustration of two cells of a film strip. + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon-web.ts b/src/elements/ia-topnav/assets/img/icon-web.ts new file mode 100644 index 00000000..a81002a9 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon-web.ts @@ -0,0 +1,19 @@ +import { html } from 'lit'; + +export default html` + + Web icon + An illustration of a computer application window + + +`; diff --git a/src/elements/ia-topnav/assets/img/icon.ts b/src/elements/ia-topnav/assets/img/icon.ts new file mode 100644 index 00000000..88d1b9a4 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icon.ts @@ -0,0 +1,8 @@ +import { LitElement } from 'lit'; +import { property } from 'lit/decorators.js'; + +export default class Icon extends LitElement { + @property({ type: Boolean }) active = false; + + @property({ type: String }) fill = 'fff'; +} diff --git a/src/elements/ia-topnav/assets/img/icons.ts b/src/elements/ia-topnav/assets/img/icons.ts new file mode 100644 index 00000000..04a5f202 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/icons.ts @@ -0,0 +1,33 @@ +import audio from './icon-audio'; +import close from './icon-close'; +import donate from './icon-donate'; +import donateUnpadded from './icon-donate-unpadded'; +import ellipses from './icon-ellipses'; +import iaLogo from './icon-ia-logo'; +import images from './icon-images'; +import search from './icon-search'; +import software from './icon-software'; +import texts from './icon-texts'; +import upload from './icon-upload'; +import uploadUnpadded from './icon-upload-unpadded'; +import user from './icon-user'; +import video from './icon-video'; +import web from './icon-web'; + +export default { + audio, + close, + donate, + donateUnpadded, + ellipses, + iaLogo, + images, + search, + software, + texts, + upload, + uploadUnpadded, + user, + video, + web, +}; diff --git a/src/elements/ia-topnav/assets/img/wayback-logo.ts b/src/elements/ia-topnav/assets/img/wayback-logo.ts new file mode 100644 index 00000000..b7cb923d --- /dev/null +++ b/src/elements/ia-topnav/assets/img/wayback-logo.ts @@ -0,0 +1,21 @@ +import { html } from 'lit'; + +export default html` + + + + + + +`; diff --git a/src/elements/ia-topnav/assets/img/wordmark-stacked.ts b/src/elements/ia-topnav/assets/img/wordmark-stacked.ts new file mode 100644 index 00000000..4276a376 --- /dev/null +++ b/src/elements/ia-topnav/assets/img/wordmark-stacked.ts @@ -0,0 +1,13 @@ +import { svg } from 'lit'; + +export default svg` + + + + + + + + + +`; diff --git a/src/elements/ia-topnav/data/menus.test.ts b/src/elements/ia-topnav/data/menus.test.ts new file mode 100644 index 00000000..c3c8891d --- /dev/null +++ b/src/elements/ia-topnav/data/menus.test.ts @@ -0,0 +1,57 @@ +import { describe, expect, test } from 'vitest'; + +import { buildTopNavMenus } from '../data/menus'; +import type { IATopNavMenuConfig } from '../models'; + +const MEDIA_CATEGORIES: (keyof IATopNavMenuConfig)[] = [ + 'texts', + 'video', + 'audio', + 'software', + 'images', + 'web', + 'more', +]; + +describe('Menu data', () => { + test.each(MEDIA_CATEGORIES)('builds a %s media menu', (category) => { + const menus = buildTopNavMenus(); + const menu = menus[category]; + + expect(menu, `${category} should be built`).to.exist; + expect(menu).to.have.property('heading'); + }); + + test('builds the signed-out and user link lists', () => { + const menus = buildTopNavMenus(); + + expect(menus.signedOut).to.be.an('array').that.is.not.empty; + expect(menus.user).to.be.an('array').that.is.not.empty; + }); + + /** + * The topnav gates each admin section on the matching list being non-empty, + * so an unset uploader or biblio has to build nothing rather than a section + * with no links in it. + */ + test('leaves the uploader and biblio sections empty when not given one', () => { + const menus = buildTopNavMenus('brewster', '', '', 'goody'); + + expect(menus.userAdminUploader).to.be.an('array').that.is.empty; + expect(menus.userAdminBiblio).to.be.an('array').that.is.empty; + }); + + test('builds the uploader and biblio sections when given both', () => { + const menus = buildTopNavMenus( + 'brewster', + '', + '', + 'goody', + 'uploader@archive.org', + 'https://openlibrary.org/search/inside?q=', + ); + + expect(menus.userAdminUploader).to.be.an('array').that.is.not.empty; + expect(menus.userAdminBiblio).to.be.an('array').that.is.not.empty; + }); +}); diff --git a/src/elements/ia-topnav/data/menus.ts b/src/elements/ia-topnav/data/menus.ts new file mode 100644 index 00000000..cc8721dd --- /dev/null +++ b/src/elements/ia-topnav/data/menus.ts @@ -0,0 +1,691 @@ +// @see https://git.archive.org/www/offshoot/-/blob/main/guides/update-top-nav.md + +import { IATopNavConfig, IATopNavMenuConfig } from '../models'; + +export const defaultTopNavConfig: IATopNavConfig = { + // Google Analytics event category + eventCategory: 'TopNav', + // Default value, if more accurate value is not passed in to `buildTopNavMenus()` + waybackPagesArchived: '1 trillion', +}; + +/** + * Creates archive.org top navigation configuration + * @param { string } userid archive.org account (immutable) userid + * @param { boolean } localLinks passing in false will ensure all links begin: https://archive.org + * @param { string } waybackPagesArchived label readable 'how many pages in WayBack machine?' + * If you don't pass in something, you'll get the potentially + * older/less accurate version. + * @param { string } itemIdentifier The current item being viewed, to populate admin menu items + * @returns { object } + */ +export function buildTopNavMenus( + userid: string = '___USERID___', + baseHost: string = 'https://archive.org', + waybackPagesArchived: string = '', + itemIdentifier: string = '', + uploader: string = '', + biblio: string = '', +): IATopNavMenuConfig { + if (waybackPagesArchived) + defaultTopNavConfig.waybackPagesArchived = waybackPagesArchived; // update to more accurate val + + return { + audio: { + heading: 'Internet Archive Audio', + iconLinks: [ + { + icon: `${baseHost}/services/img/etree`, + title: 'Live Music Archive', + url: `${baseHost}/details/etree`, + }, + { + icon: `${baseHost}/services/img/librivoxaudio`, + title: 'Librivox Free Audio', + url: `${baseHost}/details/librivoxaudio`, + }, + ], + featuredLinks: [ + { + title: 'All Audio', + url: `${baseHost}/details/audio`, + }, + { + title: 'Grateful Dead', + url: `${baseHost}/details/GratefulDead`, + }, + { + title: 'Netlabels', + url: `${baseHost}/details/netlabels`, + }, + { + title: 'Old Time Radio', + url: `${baseHost}/details/oldtimeradio`, + }, + { + title: '78 RPMs and Cylinder Recordings', + url: `${baseHost}/details/78rpm`, + }, + ], + links: [ + { + title: 'Audio Books & Poetry', + url: `${baseHost}/details/audio_bookspoetry`, + }, + { + title: 'Computers, Technology and Science', + url: `${baseHost}/details/audio_tech`, + }, + { + title: 'Music, Arts & Culture', + url: `${baseHost}/details/audio_music`, + }, + { + title: 'News & Public Affairs', + url: `${baseHost}/details/audio_news`, + }, + { + title: 'Spirituality & Religion', + url: `${baseHost}/details/audio_religion`, + }, + { + title: 'Podcasts', + url: `${baseHost}/details/podcasts`, + }, + { + title: 'Radio News Archive', + url: `${baseHost}/details/radio`, + }, + ], + mobileAppsLinks: [], + browserExtensionsLinks: [], + archiveItLinks: [], + }, + images: { + heading: 'Images', + iconLinks: [ + { + icon: `${baseHost}/services/img/metropolitanmuseumofart-gallery`, + title: 'Metropolitan Museum', + url: `${baseHost}/details/metropolitanmuseumofart-gallery`, + }, + { + icon: `${baseHost}/services/img/clevelandart`, + title: 'Cleveland Museum of Art', + url: `${baseHost}/details/clevelandart`, + }, + ], + featuredLinks: [ + { + title: 'All Images', + url: `${baseHost}/details/image`, + }, + { + title: 'Flickr Commons', + url: `${baseHost}/details/flickrcommons`, + }, + { + title: 'Occupy Wall Street Flickr', + url: `${baseHost}/details/flickr-ows`, + }, + { + title: 'Cover Art', + url: `${baseHost}/details/coverartarchive`, + }, + { + title: 'USGS Maps', + url: `${baseHost}/details/maps_usgs`, + }, + ], + links: [ + { + title: 'NASA Images', + url: `${baseHost}/details/nasa`, + }, + { + title: 'Solar System Collection', + url: `${baseHost}/details/solarsystemcollection`, + }, + { + title: 'Ames Research Center', + url: `${baseHost}/details/amesresearchcenterimagelibrary`, + }, + ], + mobileAppsLinks: [], + browserExtensionsLinks: [], + archiveItLinks: [], + }, + more: { + links: [ + { + title: 'About', + url: `${baseHost}/about/`, + }, + { + title: 'Blog', + url: 'https://blog.archive.org', + }, + { + title: 'Events', + url: `${baseHost}/events`, + }, + { + title: 'Projects', + url: `${baseHost}/projects/`, + }, + { + title: 'Help', + url: `${baseHost}/about/faqs.php`, + }, + { + title: 'Donate', + url: `${baseHost}/donate?origin=iawww-TopNavDonateButton`, + }, + { + title: 'Contact', + url: `${baseHost}/about/contact`, + }, + { + title: 'Jobs', + url: `${baseHost}/about/jobs`, + }, + { + title: 'Volunteer', + url: `${baseHost}/about/volunteer-positions`, + }, + ], + heading: '', + iconLinks: [], + featuredLinks: [], + mobileAppsLinks: [], + browserExtensionsLinks: [], + archiveItLinks: [], + }, + software: { + heading: 'Software', + iconLinks: [ + { + icon: `${baseHost}/services/img/internetarcade`, + title: 'Internet Arcade', + url: `${baseHost}/details/internetarcade`, + }, + { + icon: `${baseHost}/services/img/consolelivingroom`, + title: 'Console Living Room', + url: `${baseHost}/details/consolelivingroom`, + }, + ], + featuredLinks: [ + { + title: 'All Software', + url: `${baseHost}/details/software`, + }, + { + title: 'Old School Emulation', + url: `${baseHost}/details/tosec`, + }, + { + title: 'MS-DOS Games', + url: `${baseHost}/details/softwarelibrary_msdos_games`, + }, + { + title: 'Historical Software', + url: `${baseHost}/details/historicalsoftware`, + }, + { + title: 'Classic PC Games', + url: `${baseHost}/details/classicpcgames`, + }, + { + title: 'Software Library', + url: `${baseHost}/details/softwarelibrary`, + }, + ], + links: [ + { + title: 'Kodi Archive and Support File', + url: `${baseHost}/details/kodi_archive`, + }, + { + title: 'Vintage Software', + url: `${baseHost}/details/vintagesoftware`, + }, + { + title: 'APK', + url: `${baseHost}/details/apkarchive`, + }, + { + title: 'MS-DOS', + url: `${baseHost}/details/softwarelibrary_msdos`, + }, + { + title: 'CD-ROM Software', + url: `${baseHost}/details/cd-roms`, + }, + { + title: 'CD-ROM Software Library', + url: `${baseHost}/details/cdromsoftware`, + }, + { + title: 'Software Sites', + url: `${baseHost}/details/softwaresites`, + }, + { + title: 'Tucows Software Library', + url: `${baseHost}/details/tucows`, + }, + { + title: 'Shareware CD-ROMs', + url: `${baseHost}/details/cdbbsarchive`, + }, + { + title: 'Software Capsules Compilation', + url: `${baseHost}/details/softwarecapsules`, + }, + { + title: 'CD-ROM Images', + url: `${baseHost}/details/cdromimages`, + }, + { + title: 'ZX Spectrum', + url: `${baseHost}/details/softwarelibrary_zx_spectrum`, + }, + { + title: 'DOOM Level CD', + url: `${baseHost}/details/doom-cds`, + }, + ], + mobileAppsLinks: [], + browserExtensionsLinks: [], + archiveItLinks: [], + }, + texts: { + heading: 'Texts', + iconLinks: [ + { + title: 'Open Library', + icon: `${baseHost}/images/widgetOL.png`, + url: 'https://openlibrary.org/', + }, + { + title: 'American Libraries', + icon: `${baseHost}/services/img/americana`, + url: `${baseHost}/details/americana`, + }, + ], + featuredLinks: [ + { + title: 'All Texts', + url: `${baseHost}/details/texts`, + }, + { + title: 'Smithsonian Libraries', + url: `${baseHost}/details/smithsonian`, + }, + { + title: 'FEDLINK (US)', + url: `${baseHost}/details/fedlink`, + }, + { + title: 'Genealogy', + url: `${baseHost}/details/genealogy`, + }, + { + title: 'Lincoln Collection', + url: `${baseHost}/details/lincolncollection`, + }, + ], + links: [ + { + title: 'American Libraries', + url: `${baseHost}/details/americana`, + }, + { + title: 'Canadian Libraries', + url: `${baseHost}/details/toronto`, + }, + { + title: 'Universal Library', + url: `${baseHost}/details/universallibrary`, + }, + { + title: 'Project Gutenberg', + url: `${baseHost}/details/gutenberg`, + }, + { + title: "Children's Library", + url: `${baseHost}/details/iacl`, + }, + { + title: 'Biodiversity Heritage Library', + url: `${baseHost}/details/biodiversity`, + }, + { + title: 'Books by Language', + url: `${baseHost}/details/booksbylanguage`, + }, + { + title: 'Folkscanomy', + url: `${baseHost}/details/folkscanomy`, + }, + { + title: 'Government Documents', + url: `${baseHost}/details/government-documents`, + }, + ], + mobileAppsLinks: [], + browserExtensionsLinks: [], + archiveItLinks: [], + }, + web: { + mobileAppsLinks: [ + { + url: 'https://apps.apple.com/us/app/wayback-machine/id1201888313', + title: 'Wayback Machine (iOS)', + external: true, + }, + { + url: 'https://play.google.com/store/apps/details?id=com.internetarchive.waybackmachine', + title: 'Wayback Machine (Android)', + external: true, + }, + ], + browserExtensionsLinks: [ + { + url: 'https://chrome.google.com/webstore/detail/wayback-machine/fpnmgdkabkmnadcjpehmlllkndpkmiak', + title: 'Chrome', + external: true, + }, + { + url: 'https://addons.mozilla.org/en-US/firefox/addon/wayback-machine_new/', + title: 'Firefox', + external: true, + }, + { + url: 'https://apps.apple.com/us/app/wayback-machine/id1472432422?mt=12', + title: 'Safari', + external: true, + }, + { + url: 'https://microsoftedge.microsoft.com/addons/detail/wayback-machine/kjmickeoogghaimmomagaghnogelpcpn?hl=en-US', + title: 'Edge', + external: true, + }, + ], + archiveItLinks: [ + { + url: 'https://www.archive-it.org/explore', + title: 'Explore the Collections', + external: true, + }, + { + url: 'https://www.archive-it.org/blog/learn-more/', + title: 'Learn More', + external: true, + }, + { + url: 'https://www.archive-it.org/contact-us', + title: 'Build Collections', + external: true, + }, + ], + heading: '', + iconLinks: [], + featuredLinks: [], + links: [], + }, + video: { + heading: 'Video', + iconLinks: [ + { + icon: `${baseHost}/services/img/tv`, + title: 'TV News', + url: `${baseHost}/details/tv`, + }, + { + icon: `${baseHost}/services/img/911`, + title: 'Understanding 9/11', + url: `${baseHost}/details/911`, + }, + ], + featuredLinks: [ + { + title: 'All Video', + url: `${baseHost}/details/movies`, + }, + { + title: 'Prelinger Archives', + url: `${baseHost}/details/prelinger`, + }, + { + title: 'Democracy Now!', + url: `${baseHost}/details/democracy_now_vid`, + }, + { + title: 'Occupy Wall Street', + url: `${baseHost}/details/occupywallstreet`, + }, + { + title: 'TV NSA Clip Library', + url: `${baseHost}/details/nsa`, + }, + ], + links: [ + { + title: 'Animation & Cartoons', + url: `${baseHost}/details/animationandcartoons`, + }, + { + title: 'Arts & Music', + url: `${baseHost}/details/artsandmusicvideos`, + }, + { + title: 'Computers & Technology', + url: `${baseHost}/details/computersandtechvideos`, + }, + { + title: 'Cultural & Academic Films', + url: `${baseHost}/details/culturalandacademicfilms`, + }, + { + title: 'Ephemeral Films', + url: `${baseHost}/details/ephemera`, + }, + { + title: 'Movies', + url: `${baseHost}/details/moviesandfilms`, + }, + { + title: 'News & Public Affairs', + url: `${baseHost}/details/newsandpublicaffairs`, + }, + { + title: 'Spirituality & Religion', + url: `${baseHost}/details/spiritualityandreligion`, + }, + { + title: 'Sports Videos', + url: `${baseHost}/details/sports`, + }, + { + title: 'Television', + url: `${baseHost}/details/television`, + }, + { + title: 'Videogame Videos', + url: `${baseHost}/details/gamevideos`, + }, + { + title: 'Vlogs', + url: `${baseHost}/details/vlogs`, + }, + { + title: 'Youth Media', + url: `${baseHost}/details/youth_media`, + }, + ], + mobileAppsLinks: [], + browserExtensionsLinks: [], + archiveItLinks: [], + }, + user: [ + { + url: `${baseHost}/upload`, + title: 'Upload files', + analyticsEvent: 'UserUpload', + class: 'mobile-upload', + }, + { + url: `${baseHost}/details/@${userid}`, + title: 'My uploads', + analyticsEvent: 'UserLibrary', + }, + { + url: `${baseHost}/details/@${userid}/loans`, + title: 'My loans', + analyticsEvent: 'UserLoans', + }, + { + url: `${baseHost}/details/@${userid}/favorites`, + title: 'My favorites', + analyticsEvent: 'UserFavorites', + }, + { + url: `${baseHost}/details/@${userid}/lists`, + title: 'My lists', + analyticsEvent: 'UserLists', + }, + { + url: `${baseHost}/details/@${userid}/collections`, + title: 'My collections', + analyticsEvent: 'UserCollections', + }, + { + url: `${baseHost}/details/@${userid}/web-archive`, + title: 'My web archives', + analyticsEvent: 'UserWebArchive', + }, + { + url: `${baseHost}/account/settings`, + title: 'Account settings', + analyticsEvent: 'UserSettings', + }, + { + url: 'https://help.archive.org', + title: 'Get help', + analyticsEvent: 'UserHelp', + }, + { + url: `${baseHost}/logout`, + title: 'Log out', + analyticsEvent: 'UserLogOut', + }, + ], + userAdmin: [ + { + title: 'ADMINS:', + }, + { + title: 'item:', + }, + { + url: `${baseHost}/editxml/${itemIdentifier}`, + title: 'edit xml', + analyticsEvent: 'AdminUserEditXML', + }, + { + url: `${baseHost}/edit.php?redir=1&identifier=${itemIdentifier}`, + title: 'edit files', + analyticsEvent: 'AdminUserEditFiles', + }, + { + url: `${baseHost}/download/${itemIdentifier}/`, + title: 'download', + analyticsEvent: 'AdminUserDownload', + }, + { + url: `${baseHost}/metadata/${itemIdentifier}/`, + title: 'metadata', + analyticsEvent: 'AdminUserMetadata', + }, + { + url: `https://catalogd.archive.org/history/${itemIdentifier}`, + title: 'history', + analyticsEvent: 'AdminUserHistory', + }, + { + url: `${baseHost}/manage/${itemIdentifier}`, + title: 'manage', + analyticsEvent: 'AdminUserManager', + }, + { + url: `${baseHost}/manage/${itemIdentifier}#make_dark`, + title: 'curate', + analyticsEvent: 'AdminUserCurate', + }, + { + url: `${baseHost}/manage/${itemIdentifier}#modify_xml`, + title: 'modify xml', + analyticsEvent: 'AdminUserModifyXML', + }, + ], + userAdminFlags: [ + { + url: `${baseHost}/services/flags/admin.php?identifier=${itemIdentifier}`, + title: 'manage flags', + analyticsEvent: 'AdminUserManageFlags', + }, + ], + userAdminBiblio: biblio + ? [ + { + url: `${biblio}&ignored=${itemIdentifier}`, + title: 'biblio', + analyticsEvent: 'AdminUserBiblio', + }, + { + url: `${baseHost}/bookview.php?mode=debug&identifier=${itemIdentifier}`, + title: 'bookview', + analyticsEvent: 'AdminUserBookView', + }, + { + url: `${baseHost}/download/${itemIdentifier}/format=Single Page Processed JP2 ZIP`, + title: 'jp2 zip', + analyticsEvent: 'AdminUserJP2Zip', + }, + ] + : [], + userAdminUploader: uploader + ? [ + { + title: 'uploader:', + }, + { + title: uploader, + }, + { + url: `https://catalogd.archive.org/control/useradmin.php?email=${encodeURIComponent(uploader)}`, + title: 'user admin', + analyticsEvent: 'AdminUserUserAdmin', + }, + { + url: `https://catalogd.archive.org/control/setadmin.php?user=${encodeURIComponent(uploader)}&ignore=${itemIdentifier}`, + title: 'user privs', + analyticsEvent: 'AdminUserUserPrivs', + }, + ] + : [], + signedOut: [ + { + url: `${baseHost}/signup`, + title: 'Sign up for free', + analyticsEvent: 'AvatarMenu-Signup', + }, + { + url: `${baseHost}/login`, + title: 'Log in', + analyticsEvent: 'AvatarMenu-Login', + }, + ], + }; +} diff --git a/src/elements/ia-topnav/dropdown-menu.test.ts b/src/elements/ia-topnav/dropdown-menu.test.ts new file mode 100644 index 00000000..8ad045be --- /dev/null +++ b/src/elements/ia-topnav/dropdown-menu.test.ts @@ -0,0 +1,25 @@ +import { fixture } from '@open-wc/testing-helpers'; +import { html } from 'lit'; + +import DropdownMenu from './dropdown-menu'; + +import { describe, expect, test } from 'vitest'; +customElements.define('dropdown-menu', DropdownMenu); + +const component = html``; + +describe('', () => { + test('sets default properties', async () => { + const el = await fixture(component); + expect(el.animated).to.be.false; + expect(el.open).to.be.false; + expect(el.menuItems.length).to.equal(0); + }); + + test('renders a closed class if component is animating', async () => { + const el = await fixture(component); + el.animated = true; + await el.updateComplete; + expect(el.shadowRoot?.querySelector('.closed')).to.not.be.undefined; + }); +}); diff --git a/src/elements/ia-topnav/dropdown-menu.ts b/src/elements/ia-topnav/dropdown-menu.ts new file mode 100644 index 00000000..2833c04f --- /dev/null +++ b/src/elements/ia-topnav/dropdown-menu.ts @@ -0,0 +1,322 @@ +import { + CSSResultGroup, + PropertyValues, + TemplateResult, + css, + html, + nothing, +} from 'lit'; +import { property } from 'lit/decorators.js'; + +import icons from './assets/img/icons'; +import { defaultTopNavConfig } from './data/menus'; +import formatUrl from './lib/format-url'; +import { makeBooleanString } from './lib/make-boolean-string'; +import { + IATopNavConfig, + IATopNavLink, + TOPNAV_MOBILE_BREAKPOINT, +} from './models'; +import TrackedElement from './tracked-element'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import KeyboardNavigation from './lib/keyboard-navigation'; +import themeStyles from '@src/themes/theme-styles'; + +export default class DropdownMenu extends TrackedElement { + @property({ type: String }) baseHost = ''; + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + @property({ type: Array }) menuItems: IATopNavLink[] | IATopNavLink[][] = []; + @property({ type: Boolean }) animated = false; + @property({ type: Boolean }) open = false; + + private previousKeydownListener?: // eslint-disable-next-line @typescript-eslint/no-explicit-any + (this: HTMLElement, ev: KeyboardEvent) => any; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + :host { + /* + * Where the menu parks when closed. Nothing sets it today, so the + * fallback is what actually applies. + */ + --topnav-dropdown-closed-top--: var(--topOffset, -1500px); + /* + * Set imperatively by ia-topnav once it has measured the account + * button, so the dropdown lines up with the icon that opened it. + */ + --topnav-dropdown-right--: var(--dropdownMenuRight, 0); + } + + .nav-container { + position: relative; + } + + nav { + position: absolute; + right: 0; + z-index: 4; + overflow: hidden; + font-size: 1.6rem; + background-color: var(--dropdownMenuBg); + transition-property: top; + transition-duration: 0.2s; + transition-timing-function: ease; + } + + .initial, + .closed { + top: var(--topnav-dropdown-closed-top--); + } + + .closed { + transition-duration: 0.5s; + } + + .open { + max-width: 100vw; + overflow: auto; + } + + h3 { + padding: 0.6rem 2rem; + margin: 0; + font-size: inherit; + overflow: hidden; + text-overflow: ellipsis; + } + + ul { + padding: 0.4rem 0 0.7rem 0; + margin: 0; + list-style: none; + /* viewport height - nav height + bottom nav border */ + max-height: calc(100vh - 7.2rem + 1px); + overflow: auto; + box-sizing: border-box; + } + + .divider { + margin: 0.5rem 0; + border-bottom: 1px solid var(--dropdownMenuDivider); + } + + a, + .info-item { + display: block; + color: var(--primaryTextColor); + text-decoration: none; + padding: 1rem 2rem; + } + + .info-item { + font-size: 0.8em; + color: var(--dropdownMenuInfoItem); + } + + .callout { + position: absolute; + margin-left: 10px; + padding: 0 5px; + border-radius: 2px; + background: #fee257; + color: #2c2c2c; + font-size: 1.4rem; + font-weight: bold; + } + + a.mobile-upload { + display: flex; + justify-content: left; + align-items: center; + } + a.mobile-upload svg { + fill: var(--white); + margin-right: 1rem; + height: 1.4rem; + width: 1.4rem; + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + nav { + display: flex; + overflow: visible; + top: 0; + left: auto; + right: var(--topnav-dropdown-right--); + z-index: 5; + transition: opacity 0.2s ease-in-out; + font-size: 1.4rem; + border-radius: 2px; + background: var(--primaryTextColor); + box-shadow: 0 1px 2px 1px rgba(0, 0, 0, 0.15); + } + + nav:after { + position: absolute; + right: 7px; + top: -7px; + width: 12px; + height: 7px; + box-sizing: border-box; + color: var(--white); + content: ''; + border-bottom: 7px solid currentColor; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + } + + h3 { + display: none; + } + + ul { + /* viewport height - nav height + bottom nav border */ + max-height: calc(100vh - 8.5rem + 1px); + } + + .divider { + border-bottom-color: var(--dropdownMenuDivider); + } + + a { + padding: 0.5rem 2rem; + color: var(--inverseTextColor); + transition: + background 0.1s ease-out, + color 0.1s ease-out; + } + + .info-item { + padding: 0.5rem 2rem; + font-size: 0.8em; + color: var(--inverseDropdownMenuInfoItem); + } + + a:hover, + a:active, + a:focus { + color: var(--linkHoverColor); + background: var(--linkColor); + outline: none; + } + + .initial, + .closed { + opacity: 0; + transition-duration: 0.2s; + } + + .open { + opacity: 1; + overflow: visible; + } + + a.mobile-upload { + display: none; + } + } + `, + ]; + } + + updated(props: PropertyValues) { + if (props.has('open') && this.open) { + const container = this.shadowRoot?.querySelector( + '.nav-container', + ) as HTMLElement; + + if (container) { + const keyboardNavigation = new KeyboardNavigation( + container, + 'usermenu', + ); + this.addEventListener('keydown', keyboardNavigation.handleKeyDown); + if (this.previousKeydownListener) { + this.removeEventListener('keydown', this.previousKeydownListener); + } + this.previousKeydownListener = keyboardNavigation.handleKeyDown; + } + } + } + + get dropdownItems() { + if (!this.menuItems) return nothing; + + if (!Array.isArray(this.menuItems[0])) { + const submenu = this.menuItems as IATopNavLink[]; + return this.dropdownSection(submenu); + } + return this.menuItems.map((submenu, i) => { + const joiner = i ? DropdownMenu.dropdownDivider : html``; + if (!Array.isArray(submenu)) { + return; + } + return [joiner, ...this.dropdownSection(submenu)]; + }); + } + + static get dropdownDivider() { + return html`

  • `; + } + + private dropdownSection(submenu: IATopNavLink[]): TemplateResult[] { + return submenu.map( + (item) => html` +
  • + ${item.url + ? this.dropdownLink(item) + : DropdownMenu.dropdownText(item)} +
  • + `, + ); + } + + dropdownLink(link: IATopNavLink): TemplateResult { + const calloutText = this.config?.callouts?.[link.title]; + const isMobileUpload = link.class === 'mobile-upload'; + const isTabbable = this.open && !isMobileUpload; + + return html` + ${isMobileUpload ? icons.uploadUnpadded : nothing} ${link.title} + ${calloutText + ? html`` + : nothing} + `; + } + + static dropdownText(item: IATopNavLink) { + return html`${item.title}`; + } + + get menuClass() { + if (this.open) return 'open'; + if (this.animated) return 'closed'; + return 'initial'; + } + + render() { + return html` + + `; + } +} diff --git a/src/elements/ia-topnav/element-names.test.ts b/src/elements/ia-topnav/element-names.test.ts new file mode 100644 index 00000000..bb43c8e9 --- /dev/null +++ b/src/elements/ia-topnav/element-names.test.ts @@ -0,0 +1,81 @@ +import { describe, expect, test } from 'vitest'; + +import './ia-topnav'; +import './ia-topnav-desktop-subnav'; +import './ia-topnav-icon-hamburger'; +import './ia-topnav-login-button'; +import './ia-topnav-media-button'; +import './ia-topnav-media-menu'; +import './ia-topnav-media-slider'; +import './ia-topnav-media-subnav'; +import './ia-topnav-more-slider'; +import './ia-topnav-primary-nav'; +import './ia-topnav-save-page-form'; +import './ia-topnav-signed-out-dropdown'; +import './ia-topnav-user-menu'; +import './ia-topnav-wayback-search'; +import './ia-topnav-wayback-slider'; + +/** + * Custom elements share one global registry, so the topnav's parts are + * namespaced under its own prefix rather than taking names on their own. + */ +const NAMESPACED_ELEMENTS = [ + 'ia-topnav-desktop-subnav', + 'ia-topnav-icon-hamburger', + 'ia-topnav-login-button', + 'ia-topnav-media-button', + 'ia-topnav-media-menu', + 'ia-topnav-media-slider', + 'ia-topnav-media-subnav', + 'ia-topnav-more-slider', + 'ia-topnav-primary-nav', + 'ia-topnav-save-page-form', + 'ia-topnav-signed-out-dropdown', + 'ia-topnav-user-menu', + 'ia-topnav-wayback-search', + 'ia-topnav-wayback-slider', +]; + +/** + * Names this component must not claim. Every one is registered verbatim by the + * `@internetarchive/ia-topnav` package, which petabox and offshoot both still + * load, and a second registration of the same name throws rather than + * degrading. `ia-wayback-search` comes along with them because importing + * `@internetarchive/ia-wayback-search` registers it as a side effect, and + * `ia-icon` is generic enough that any page could want it. + */ +const NAMES_TO_AVOID = [ + 'desktop-subnav', + 'dropdown-menu', + 'ia-icon', + 'ia-wayback-search', + 'icon-hamburger', + 'login-button', + 'media-button', + 'media-menu', + 'media-slider', + 'media-subnav', + 'more-slider', + 'primary-nav', + 'save-page-form', + 'signed-out-dropdown', + 'user-menu', + 'wayback-search', + 'wayback-slider', +]; + +describe('topnav element names', () => { + test('registers the topnav under its own name', () => { + expect(customElements.get('ia-topnav')).to.exist; + }); + + test.each(NAMESPACED_ELEMENTS)('registers %s', (tag) => { + expect(customElements.get(tag), `${tag} should be registered`).to.exist; + }); + + test.each(NAMES_TO_AVOID)('leaves %s free for other components', (tag) => { + expect(customElements.get(tag), `${tag} should not be claimed`).to.not + .exist; + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts b/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts new file mode 100644 index 00000000..09b0a0b8 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts @@ -0,0 +1,87 @@ +import { CSSResultGroup, TemplateResult, css, html, nothing } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +import TrackedElement from './tracked-element'; +import icons from './assets/img/icons'; +import formatUrl from './lib/format-url'; +import { IATopNavLink } from './models'; +import themeStyles from '@src/themes/theme-styles'; + +@customElement('ia-topnav-desktop-subnav') +export class DesktopSubnav extends TrackedElement { + @property({ type: String }) baseHost = ''; + @property({ type: Array }) menuItems: IATopNavLink[] = []; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + ul { + position: relative; + z-index: 3; + padding: 0.8rem 0; + margin: 0; + font-size: 1.2rem; + text-transform: uppercase; + text-align: center; + background: var(--desktopSubnavBg); + } + + li { + display: inline-block; + padding: 0 15px; + } + + a { + text-decoration: none; + color: var(--subnavLinkColor); + outline: none; + } + + a:hover, + a:active, + a:focus { + color: var(--linkHoverColor); + } + + .donate svg { + width: 1.6rem; + height: 1.6rem; + vertical-align: top; + fill: #f00; + } + `, + ]; + } + + get listItems() { + return this.menuItems + ? this.menuItems.map( + (link) => html` +
  • + ${link.title}${DesktopSubnav.iconFor(link.title)} +
  • + `, + ) + : nothing; + } + + static iconFor(title: string): TemplateResult { + const subnavIcons: Record = { + Donate: icons.donate, + }; + return subnavIcons[title] ? subnavIcons[title] : html``; + } + + render() { + return html` +
      + ${this.listItems} +
    + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-icon-hamburger.test.ts b/src/elements/ia-topnav/ia-topnav-icon-hamburger.test.ts new file mode 100644 index 00000000..ebe6ac62 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-icon-hamburger.test.ts @@ -0,0 +1,20 @@ +import { fixture } from '@open-wc/testing-helpers'; +import { html } from 'lit'; +import './ia-topnav-icon-hamburger'; +import { HamBurger } from './ia-topnav-icon-hamburger'; + +import { describe, expect, test } from 'vitest'; +describe('', () => { + test('toggles close icon when property toggled', async () => { + const icon = await fixture( + html``, + ); + + icon.active = true; + await icon.updateComplete; + + const titleElement = icon.shadowRoot?.querySelector('svg title'); + + expect(titleElement?.getAttribute('id')).to.match(/close/); + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts b/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts new file mode 100644 index 00000000..adc5358c --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts @@ -0,0 +1,49 @@ +import { html, css } from 'lit'; +import Icon from './assets/img/icon'; +import icons from './assets/img/icons'; +import { customElement } from 'lit/decorators.js'; + +@customElement('ia-topnav-icon-hamburger') +export class HamBurger extends Icon { + static get styles() { + return css` + svg { + display: block; + height: 4rem; + width: 4rem; + } + .fill-color { + fill: var(--activeColor); + } + `; + } + + static get closed() { + return html` + + Hamburger icon + + An icon used to represent a menu that can be toggled by interacting + with this icon. + + + + `; + } + + static get opened() { + return icons.close; + } + + render() { + return this.active ? HamBurger.opened : HamBurger.closed; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-login-button.test.ts b/src/elements/ia-topnav/ia-topnav-login-button.test.ts new file mode 100644 index 00000000..d0477be7 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-login-button.test.ts @@ -0,0 +1,21 @@ +import { fixture } from '@open-wc/testing-helpers'; +import { html } from 'lit'; +import './ia-topnav-login-button'; +import { LoginButton } from './ia-topnav-login-button'; + +import { describe, expect, test } from 'vitest'; +const component = html``; + +describe('', () => { + test('toggles active class when avatar clicked', async () => { + const el = await fixture(component); + const toggle = el.shadowRoot?.querySelector( + '.dropdown-toggle', + ) as HTMLAnchorElement; + + toggle?.click(); + await el.updateComplete; + + expect(el.shadowRoot?.querySelector('.active')).to.not.be.undefined; + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-login-button.ts b/src/elements/ia-topnav/ia-topnav-login-button.ts new file mode 100644 index 00000000..038a2662 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-login-button.ts @@ -0,0 +1,176 @@ +import { CSSResultGroup, css, html } from 'lit'; +import TrackedElement from './tracked-element'; +import icons from './assets/img/icons'; +import formatUrl from './lib/format-url'; +import { makeBooleanString } from './lib/make-boolean-string'; +import { customElement, property, query } from 'lit/decorators.js'; +import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; +import { defaultTopNavConfig } from './data/menus'; +import themeStyles from '@src/themes/theme-styles'; + +@customElement('ia-topnav-login-button') +export class LoginButton extends TrackedElement { + @property({ type: String }) baseHost = ''; + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + @property({ type: String }) openMenu = ''; + + @query('button.logged-out-menu') private toggleButton?: HTMLButtonElement; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + .logged-out-menu { + background: inherit; + border: none; + } + .logged-out-menu:focus-visible { + outline: none; + border: none; + } + .dropdown-toggle { + display: block; + text-transform: uppercase; + color: var(--grey80); + cursor: pointer; + } + + .dropdown-toggle svg { + height: 100%; + width: 4rem; + } + + .dropdown-toggle .fill-color { + fill: var(--iconFill); + } + + .dropdown-toggle:active .fill-color, + .dropdown-toggle:focus .fill-color, + .dropdown-toggle:hover .fill-color { + fill: var(--linkHoverColor); + } + + .active { + border-radius: 1rem 1rem 0 0; + background: var(--activeButtonBg); + } + + .active .fill-color { + fill: var(--activeColor); + } + + span { + display: none; + font-size: 1.4rem; + text-transform: uppercase; + color: var(--loginTextColor); + } + + span a { + color: inherit; + text-decoration: none; + outline: 0; + } + + a:hover, + a:active, + a:focus { + color: var(--linkHoverColor) !important; + outline: none !important; + outline-offset: inherit !important; + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + .logged-out-toolbar { + padding: 1rem 0.5rem; + vertical-align: middle; + } + + .active { + background: transparent; + } + + .dropdown-toggle { + display: inline-block; + vertical-align: middle; + } + + .dropdown-toggle svg { + height: 3rem; + width: 3rem; + display: block; + } + + span { + display: inline; + vertical-align: middle; + } + } + `, + ]; + } + + /** Distance (px) from this element's right edge to the right edge of the dropdown toggle icon. */ + getDropdownToggleOffset(): number { + if (!this.toggleButton) return 0; + return ( + this.getBoundingClientRect().right - + this.toggleButton.getBoundingClientRect().right + ); + } + + get signupPath() { + return formatUrl('/signup', this.baseHost); + } + + get loginPath() { + return formatUrl('/login', this.baseHost); + } + + get analyticsEvent() { + return `${this.config?.eventCategory}|NavLoginIcon`; + } + + get menuOpened(): boolean { + return this.openMenu === 'login'; + } + + get avatarClass() { + return `dropdown-toggle${this.menuOpened ? ' active' : ''}`; + } + + toggleDropdown(e: Event) { + e.preventDefault(); + this.trackClick(e); + this.dispatchEvent( + new CustomEvent('menuToggled', { + bubbles: true, + composed: true, + detail: { + menuName: 'login', + }, + }), + ); + } + + render() { + return html` +
    + + + Sign up + | + Log in + +
    + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-media-button.test.ts b/src/elements/ia-topnav/ia-topnav-media-button.test.ts new file mode 100644 index 00000000..a592eb8e --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-media-button.test.ts @@ -0,0 +1,23 @@ +import { fixture, oneEvent } from '@open-wc/testing-helpers'; +import { html } from 'lit'; + +import './ia-topnav-media-button'; +import { MediaButton } from './ia-topnav-media-button'; + +import { describe, expect, test } from 'vitest'; +describe('', () => { + test('emits an event when button pressed', async () => { + const el = await fixture( + html``, + ); + + const link = el.shadowRoot?.querySelector( + '.menu-item', + ) as HTMLAnchorElement; + + setTimeout(() => link.click()); + const response = await oneEvent(el, 'mediaTypeSelected'); + + expect(response).to.exist; + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-media-button.ts b/src/elements/ia-topnav/ia-topnav-media-button.ts new file mode 100644 index 00000000..c022fc6f --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-media-button.ts @@ -0,0 +1,259 @@ +import { CSSResultGroup, TemplateResult, css, html } from 'lit'; +import TrackedElement from './tracked-element'; +import icons from './assets/img/icons'; +import toSentenceCase from './lib/t-sentence-case'; +import { customElement, property } from 'lit/decorators.js'; +import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; +import { defaultTopNavConfig } from './data/menus'; +import themeStyles from '@src/themes/theme-styles'; + +@customElement('ia-topnav-media-button') +export class MediaButton extends TrackedElement { + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + @property({ type: String }) icon = ''; + @property({ type: String }) href = ''; + @property({ type: String }) label = ''; + @property({ type: String }) mediatype = ''; + @property({ type: String }) openMenu = ''; + @property({ type: Boolean }) selected = false; + @property({ type: Boolean }) followable = false; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + a { + display: inline-block; + text-decoration: none; + } + + .menu-item { + display: inline-block; + width: 100%; + padding: 0; + font-size: 1.6rem; + text-align: left; + background: transparent; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } + + .menu-item:focus { + outline: none; + } + + .label { + display: inline-block; + padding: 0; + font-weight: 400; + color: var(--primaryTextColor); + text-align: left; + vertical-align: middle; + } + + .menu-item > .icon { + display: inline-flex; + vertical-align: middle; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + } + + .menu-item > .icon > svg { + height: 4rem; + width: 4rem; + } + + .menu-item.selected .icon { + background-color: var(--activeButtonBg); + border-radius: 1rem 0 0 1rem; + } + + .icon .fill-color { + fill: #999; + } + + .icon.active .fill-color { + fill: #fff; + } + + .donate .fill-color { + fill: #f00; + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + .menu-item { + width: auto; + height: 5rem; + color: var(--mediaLabelDesktopColor); + display: inline-flex; + } + .menu-item:hover, + .menu-item:active, + .menu-item:focus { + color: var(--linkHoverColor); + } + + .menu-item:hover .fill-color, + .menu-item:active .fill-color, + .menu-item:focus .fill-color { + fill: var(--linkHoverColor); + } + + .label { + display: none; + } + + .label, + .web:after { + padding-right: 1rem; + font-size: 1.3rem; + text-transform: uppercase; + color: inherit; + } + + .web:after { + display: none; + content: 'web'; + } + .donate, + .more { + display: none; + } + + .menu-item.selected { + background: var(--activeDesktopMenuIcon); + } + + .menu-item.selected .label, + .menu-item.selected.web:after { + color: var(--linkHoverColor); + } + + .menu-item.selected .icon { + background: transparent; + } + + /* selected state icon colors */ + .web.selected .fill-color { + fill: #ffcd27; + } + + .texts.selected .fill-color { + fill: #faab3c; + } + + .video.selected .fill-color { + fill: #f1644b; + } + + .audio.selected .fill-color { + fill: #00adef; + } + + .software.selected .fill-color { + fill: #9ecc4f; + } + + .images.selected .fill-color { + fill: #aa99c9; + } + } + + @media (min-width: 1200px) { + .label, + .web:after { + display: inline; + } + + .web .label { + display: none; + } + } + `, + ]; + } + + static get icons(): Record { + return icons; + } + + onClick(e: Event) { + this.trackClick(e); + e.preventDefault(); + // On desktop viewport widths, the media subnav is always visible. To + // ensure the media subnav is open on mobile if the viewport is + // resized, the openMenu needs to be set to 'media'. + if (this.openMenu !== 'media') { + this.dispatchMenuToggledEvent(); + } + this.dispatchMediaTypeSelectedEvent(); + } + + dispatchMenuToggledEvent() { + this.dispatchEvent( + new CustomEvent('menuToggled', { + bubbles: true, + composed: true, + detail: { + menuName: 'media', + }, + }), + ); + } + + dispatchMediaTypeSelectedEvent() { + this.dispatchEvent( + new CustomEvent('mediaTypeSelected', { + bubbles: true, + composed: true, + detail: { + mediatype: this.mediatype, + }, + }), + ); + } + + get buttonClass() { + return this.selected ? 'selected' : ''; + } + + get tooltipPrefix() { + return this.selected ? 'Collapse' : 'Expand'; + } + + get iconClass() { + return this.selected ? 'active' : ''; + } + + get analyticsEvent() { + return `${this.config.eventCategory}|NavMenu${toSentenceCase(this.mediatype)}`; + } + + get menuItem() { + return html` + + ${MediaButton.icons[this.icon]} + + ${this.label} + `; + } + + render() { + return html` + + ${this.menuItem} + + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-media-menu.test.ts b/src/elements/ia-topnav/ia-topnav-media-menu.test.ts new file mode 100644 index 00000000..e8286edc --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-media-menu.test.ts @@ -0,0 +1,44 @@ +import { fixture } from '@open-wc/testing-helpers'; +import { html } from 'lit'; + +import './ia-topnav-media-menu'; +import { MediaMenu } from './ia-topnav-media-menu'; + +import { describe, expect, test } from 'vitest'; +const component = html``; + +describe('', () => { + test('sets default properties', async () => { + const mediaMenu = await fixture(component); + + expect(mediaMenu.openMenu).to.equal(''); + expect(mediaMenu.selectedMenuOption).to.equal(''); + }); + + test('renders menu icon as selected when selectedMenuOption matches', async () => { + const mediaMenu = await fixture(component); + const mediaType = 'texts'; + + mediaMenu.selectedMenuOption = mediaType; + await mediaMenu.updateComplete; + + const textsButton = mediaMenu.shadowRoot + ?.querySelector(`[data-mediatype=${mediaType}`) + ?.shadowRoot?.querySelector('.selected'); + + expect(textsButton).to.not.be.null; + }); + + test('renders with closed class if done animating', async () => { + const mediaMenu = await fixture(component); + + // mediaMenu.mediaMenuAnimate = true; + // await mediaMenu.updateComplete; + + expect( + mediaMenu.shadowRoot + ?.querySelector('.media-menu-container') + ?.classList.contains('closed'), + ).to.be.true; + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-media-menu.ts b/src/elements/ia-topnav/ia-topnav-media-menu.ts new file mode 100644 index 00000000..eb1a4f71 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-media-menu.ts @@ -0,0 +1,209 @@ +import { CSSResultGroup, LitElement, PropertyValues, css, html } from 'lit'; +import { customElement, property, queryAll } from 'lit/decorators.js'; + +import { defaultTopNavConfig } from './data/menus'; +import formatUrl from './lib/format-url'; +import './ia-topnav-media-button'; +import { MediaButton } from './ia-topnav-media-button'; +import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; +import themeStyles from '@src/themes/theme-styles'; + +const menuSelection = [ + { + icon: 'web', + menu: 'web', + href: 'https://web.archive.org', + label: 'Wayback Machine', + }, + { + icon: 'texts', + menu: 'texts', + href: '/details/texts', + label: 'Texts', + }, + { + icon: 'video', + menu: 'video', + href: '/details/movies', + label: 'Video', + }, + { + icon: 'audio', + menu: 'audio', + href: '/details/audio', + label: 'Audio', + }, + { + icon: 'software', + menu: 'software', + href: '/details/software', + label: 'Software', + }, + { + icon: 'images', + menu: 'images', + href: '/details/image', + label: 'Images', + }, + { + icon: 'donate', + menu: 'donate', + href: '/donate/?origin=iawww-mbhmbgrmenu', + label: 'Donate', + followable: true, + }, + { + icon: 'ellipses', + menu: 'more', + href: '/about/', + label: 'More', + }, +]; + +@customElement('ia-topnav-media-menu') +export class MediaMenu extends LitElement { + @property({ type: String }) baseHost = ''; + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + @property({ type: String }) openMenu = ''; + @property({ type: String }) selectedMenuOption = ''; + @property({ type: Object }) currentTab: { moveTo: string } | undefined; + + @queryAll('ia-topnav-media-button') mediaButtons?: MediaButton[]; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + :host { + outline: none; + } + + .media-menu-inner { + z-index: -1; + top: -40rem; + background-color: var(--mediaMenuBg); + margin: 0; + overflow: hidden; + transition-duration: 0.2s; + transition-property: top; + transition-timing-function: ease; + } + + .menu-group { + position: relative; + line-height: normal; + } + + /* Mobile view styles */ + @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { + .media-menu-inner { + position: absolute; + width: 100%; + } + + .open .media-menu-inner { + top: 0; + } + + .overflow-clip { + position: absolute; + z-index: -1; /** needs to be under the navigation, otherwise it intercepts clicks */ + top: 4rem; + left: 0; + height: 0; + width: 100%; + overflow: hidden; + transition-duration: 0.2s; + transition-property: height; + } + + .open .overflow-clip { + height: 40rem; + } + } + + /* Desktop view styles */ + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + .media-menu-inner { + display: block; + position: static; + width: auto; + height: 5rem; + transition-property: none; + } + + .menu-group { + font-size: 0; + } + } + `, + ]; + } + + updated(props: PropertyValues) { + if (props.has('currentTab')) { + const mediaButtons = Array.from(this.mediaButtons ?? []); + + mediaButtons.map((button, index) => { + const linkItem = button.shadowRoot?.querySelector('a.menu-item'); + if (linkItem) { + if (linkItem.classList.contains(`${this.selectedMenuOption}`)) { + linkItem.classList.remove('selected'); + (linkItem as HTMLElement).blur(); + + const newFocusIndex = + this.currentTab?.moveTo === 'next' ? index + 1 : index - 1; + ( + mediaButtons[newFocusIndex]?.shadowRoot?.querySelector( + 'a.menu-item', + ) as HTMLElement + ).focus(); + } + } + }); + } + } + + get mediaMenuOptionsTemplate() { + const buttons = menuSelection.map( + ({ icon, menu, label, href, followable }) => { + const selected = this.selectedMenuOption === menu; + return html` + + `; + }, + ); + return buttons; + } + + get menuOpened() { + return this.openMenu === 'media'; + } + + get menuClass() { + return this.menuOpened ? 'open' : 'closed'; + } + + render() { + return html` +
    +
    + +
    +
    + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-media-slider.test.ts b/src/elements/ia-topnav/ia-topnav-media-slider.test.ts new file mode 100644 index 00000000..fc3a1d8d --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-media-slider.test.ts @@ -0,0 +1,65 @@ +import { fixture } from '@open-wc/testing-helpers'; +import { html } from 'lit'; + +import './ia-topnav-media-slider'; +import { buildTopNavMenus } from './data/menus'; +import { MediaSlider } from './ia-topnav-media-slider'; + +import { describe, expect, test } from 'vitest'; +const menus = buildTopNavMenus(); + +const component = (mediaSliderOpen: boolean, selectedMenuOption: string) => + html``; + +describe('', () => { + test('sets default properties', async () => { + const mediaSlider = await fixture(component(false, '')); + + expect(mediaSlider.mediaSliderOpen).to.be.false; + expect(mediaSlider.selectedMenuOption).to.equal(''); + }); + + test('renders a media subnav when texts selected', async () => { + const mediaSlider = await fixture(component(false, 'texts')); + const menuHeading = mediaSlider.shadowRoot + ?.querySelector('ia-topnav-media-subnav[menu=texts]') + ?.shadowRoot?.querySelector('h3'); + expect(menuHeading?.innerText).to.equal(menus.texts.heading); + }); + + test('renders a media subnav when audio selected', async () => { + const mediaSlider = await fixture(component(false, 'audio')); + const menuHeading = mediaSlider.shadowRoot + ?.querySelector('ia-topnav-media-subnav[menu=audio]') + ?.shadowRoot?.querySelector('h3'); + expect(menuHeading?.innerText).to.equal(menus.audio.heading); + }); + + test('renders a media subnav when video selected', async () => { + const mediaSlider = await fixture(component(false, 'video')); + const menuHeading = mediaSlider.shadowRoot + ?.querySelector('ia-topnav-media-subnav[menu=video]') + ?.shadowRoot?.querySelector('h3'); + expect(menuHeading?.innerText).to.equal(menus.video.heading); + }); + + test('renders the Wayback component when web menu selected', async () => { + const mediaSlider = await fixture(component(false, 'web')); + const waybackSearch = mediaSlider.shadowRoot + ?.querySelector('ia-topnav-media-subnav[menu=web]') + ?.shadowRoot?.querySelector('ia-topnav-wayback-search'); + expect(waybackSearch).to.not.be.undefined; + }); + + test('renders the more links component when more menu selected', async () => { + const mediaSlider = await fixture(component(false, 'more')); + const moreSlider = mediaSlider.shadowRoot + ?.querySelector('ia-topnav-media-subnav[menu=more]') + ?.shadowRoot?.querySelector('ia-topnav-more-slider'); + expect(moreSlider).to.not.be.undefined; + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-media-slider.ts b/src/elements/ia-topnav/ia-topnav-media-slider.ts new file mode 100644 index 00000000..c75ae43b --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-media-slider.ts @@ -0,0 +1,216 @@ +import { CSSResultGroup, LitElement, PropertyValues, css, html } from 'lit'; +import './ia-topnav-media-subnav'; +import KeyboardNavigation from './lib/keyboard-navigation'; +import { customElement, property } from 'lit/decorators.js'; +import { + IATopNavConfig, + IATopNavMenuConfig, + TOPNAV_MOBILE_BREAKPOINT, +} from './models'; +import { buildTopNavMenus, defaultTopNavConfig } from './data/menus'; +import themeStyles from '@src/themes/theme-styles'; + +@customElement('ia-topnav-media-slider') +export class MediaSlider extends LitElement { + @property({ type: String }) baseHost = ''; + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + @property({ type: Boolean }) mediaSliderOpen = false; + @property({ type: Object }) menus: IATopNavMenuConfig = buildTopNavMenus(); + @property({ type: String }) selectedMenuOption = 'texts'; + + private previousKeydownListener: // eslint-disable-next-line @typescript-eslint/no-explicit-any + ((this: HTMLElement, ev: KeyboardEvent) => any) | undefined; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + .media-slider-container { + position: relative; + } + + .overflow-clip { + display: none; + position: absolute; + top: 0; + right: 0; + left: 0; + height: 0; + overflow: hidden; + transition: height 0.2s ease; + } + + .information-menu { + position: absolute; + top: 0; + right: 0; + left: 0; + padding: 0; + height: 31.9rem; + overflow-x: hidden; + font-size: 1.4rem; + background: var(--mediaSliderBg); + } + + .open { + display: block; + } + + .hidden { + display: none; + } + + .info-box { + padding: 1rem; + } + + @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { + .overflow-clip.open { + display: block; + height: 35.8rem; + left: 4rem; + top: 0; + } + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + .overflow-clip { + display: block; + } + + .information-menu { + left: 0; + z-index: 3; + height: auto; + min-height: 21rem; + background: var(--mediaSliderDesktopBg); + transform: translate(0, -100%); + transition: transform 0.2s ease; + } + + .overflow-clip.open { + height: 22rem; + } + + .information-menu.open { + transform: translate(0, 0); + } + + .info-box { + max-width: 100rem; + padding: 1.5rem 0; + margin: 0 auto; + } + } + `, + ]; + } + + updated(props: PropertyValues) { + if (props.has('selectedMenuOption') && this.selectedMenuOption) { + const container = + this.shadowRoot?.querySelector('.has-focused')?.shadowRoot; + if (container) { + const keyboardNavigation = new KeyboardNavigation( + container as unknown as HTMLElement, + this.selectedMenuOption, + ); + + if (this.previousKeydownListener) { + this.removeEventListener('keydown', this.previousKeydownListener); + } + this.addEventListener('keydown', keyboardNavigation.handleKeyDown); + this.previousKeydownListener = keyboardNavigation.handleKeyDown; + } + } + } + + shouldUpdate() { + const scrollPane = this.shadowRoot + ? this.shadowRoot.querySelector('.information-menu') + : null; + + if (scrollPane) { + scrollPane.scrollTop = 0; + } + return true; + } + + render() { + const sliderDetailsClass = this.mediaSliderOpen ? 'open' : 'closed'; + + return html` +
    +
    +
    +
    + + + + + + + +
    +
    +
    +
    + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-media-subnav.ts b/src/elements/ia-topnav/ia-topnav-media-subnav.ts new file mode 100644 index 00000000..7d4b4590 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-media-subnav.ts @@ -0,0 +1,294 @@ +import { CSSResultGroup, css, html } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; + +import TrackedElement from './tracked-element'; +import './ia-topnav-wayback-slider'; +import './ia-topnav-more-slider'; +import toSentenceCase from './lib/t-sentence-case'; +import formatUrl from './lib/format-url'; +import { customElement, property } from 'lit/decorators.js'; +import { + IATopNavConfig, + IATopNavLink, + IATopNavMediaMenu, + TOPNAV_MOBILE_BREAKPOINT, +} from './models'; +import { defaultTopNavConfig } from './data/menus'; +import { subnavListCSS } from './subnav-list-styles'; +import themeStyles from '@src/themes/theme-styles'; + +@customElement('ia-topnav-media-subnav') +export class MediaSubnav extends TrackedElement { + @property({ type: String }) baseHost = ''; + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + @property({ type: String }) menu: + | '' + | 'web' + | 'more' + | 'audio' + | 'images' + | 'software' + | 'texts' + | 'video' = ''; + @property({ type: Object }) menuItems: IATopNavMediaMenu = + MediaSubnav.defaultLinks; + + private links: IATopNavMediaMenu = MediaSubnav.defaultLinks; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + subnavListCSS, + css` + img { + display: block; + width: 90px; + height: 90px; + margin: 0 auto 1rem auto; + border-radius: 45px; + } + + h3 { + margin-top: 0; + font-size: 1.8rem; + } + + .icon-links { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: space-evenly; + -ms-flex-pack: space-evenly; + justify-content: space-evenly; + text-align: center; + } + + .icon-links a { + display: inline-block; + width: 12rem; + margin-bottom: 1.5rem; + overflow: hidden; + white-space: nowrap; + text-align: center; + text-overflow: ellipsis; + } + + .icon-links a + a { + margin-left: 2rem; + } + + .featured h4 { + display: none; + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + :host { + display: -ms-grid; + display: grid; + -ms-grid-columns: 40% 20% 40%; + grid-template-columns: 40% 20% 40%; + } + + .wayback-search { + -ms-grid-column: 1; + -ms-grid-column-span: 3; + grid-column: 1 / 4; + } + + h3 { + display: none; + } + + .icon-links { + -ms-grid-column: 1; + } + + .icon-links a { + padding-top: 3.5rem; + max-width: 16rem; + } + + .links { + padding: 0 1.5rem; + } + + .featured { + -ms-grid-column: 2; + } + + .featured h4 { + display: block; + } + + .top { + -ms-grid-column: 3; + } + + .top ul { + display: -ms-grid; + display: grid; + -ms-grid-columns: 50% 3rem 50%; + grid-template-columns: 50% 50%; + -ms-grid-rows: (auto) [7]; + grid-template-rows: repeat(7, auto); + grid-column-gap: 3rem; + grid-auto-flow: column; + } + .top ul > *:nth-child(1) { + -ms-grid-row: 1; + -ms-grid-column: 1; + } + .top ul > *:nth-child(2) { + -ms-grid-row: 2; + -ms-grid-column: 1; + } + .top ul > *:nth-child(3) { + -ms-grid-row: 3; + -ms-grid-column: 1; + } + .top ul > *:nth-child(4) { + -ms-grid-row: 4; + -ms-grid-column: 1; + } + .top ul > *:nth-child(5) { + -ms-grid-row: 5; + -ms-grid-column: 1; + } + .top ul > *:nth-child(6) { + -ms-grid-row: 6; + -ms-grid-column: 1; + } + .top ul > *:nth-child(7) { + -ms-grid-row: 7; + -ms-grid-column: 1; + } + .top ul > *:nth-child(8) { + -ms-grid-row: 1; + -ms-grid-column: 3; + } + .top ul > *:nth-child(9) { + -ms-grid-row: 2; + -ms-grid-column: 3; + } + .top ul > *:nth-child(10) { + -ms-grid-row: 3; + -ms-grid-column: 3; + } + .top ul > *:nth-child(11) { + -ms-grid-row: 4; + -ms-grid-column: 3; + } + .top ul > *:nth-child(12) { + -ms-grid-row: 5; + -ms-grid-column: 3; + } + .top ul > *:nth-child(13) { + -ms-grid-row: 6; + -ms-grid-column: 3; + } + .top ul > *:nth-child(14) { + -ms-grid-row: 7; + -ms-grid-column: 3; + } + } + `, + ]; + } + + shouldUpdate() { + if (this.menuItems) { + this.links = this.menuItems; + } + return true; + } + + static get defaultLinks(): IATopNavMediaMenu { + return { + heading: '', + iconLinks: [], + featuredLinks: [], + links: [], + mobileAppsLinks: [], + browserExtensionsLinks: [], + archiveItLinks: [], + }; + } + + analyticsEvent(title: string) { + return `${this.config?.eventCategory}|${toSentenceCase(title)}${toSentenceCase(this.menu)}`; + } + + get iconLinks() { + return this.links.iconLinks.map( + (link) => html` + ${link.title} + `, + ); + } + + renderLinks(links: IATopNavLink[]) { + return links.map( + (link) => html` +
  • + ${link.title} +
  • + `, + ); + } + + render() { + if (!this.menu) { + return html``; + } + + if (this.menuItems) { + this.links = this.menuItems; + } + + if (this.menu === 'web') { + return html` `; + } + + if (this.menu === 'more') { + return html` + `; + } + + return html` +

    ${this.links.heading}

    + + + + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-more-slider.test.ts b/src/elements/ia-topnav/ia-topnav-more-slider.test.ts new file mode 100644 index 00000000..7b12a923 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-more-slider.test.ts @@ -0,0 +1,23 @@ +import { fixture } from '@open-wc/testing-helpers'; +import { html } from 'lit'; +import './ia-topnav-more-slider'; +import { buildTopNavMenus } from './data/menus'; + +import { describe, expect, test } from 'vitest'; +describe('', () => { + test('renders links with relative hrefs using baseHost', async () => { + const menus = buildTopNavMenus(); + const baseHost = 'archive.org'; + const el = await fixture( + html``, + ); + + expect(el.shadowRoot?.querySelector('a')?.getAttribute('href')).to.contain( + baseHost, + ); + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-more-slider.ts b/src/elements/ia-topnav/ia-topnav-more-slider.ts new file mode 100644 index 00000000..c4ee0fb9 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-more-slider.ts @@ -0,0 +1,57 @@ +import { CSSResultGroup, css, html } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +import TrackedElement from './tracked-element'; +import toSentenceCase from './lib/t-sentence-case'; +import formatUrl from './lib/format-url'; +import { IATopNavConfig, IATopNavLink } from './models'; +import { defaultTopNavConfig } from './data/menus'; +import themeStyles from '@src/themes/theme-styles'; + +@customElement('ia-topnav-more-slider') +export class MoreSlider extends TrackedElement { + @property({ type: String }) baseHost = ''; + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + @property({ type: Array }) menuItems: IATopNavLink[] = []; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + ul { + padding: 0; + margin: -1rem 0 0 0; + list-style: none; + } + a { + display: block; + padding: 1rem 0; + text-decoration: none; + color: var(--activeColor); + } + `, + ]; + } + + analyticsEvent(title: string) { + return `${this.config.eventCategory}|NavMore${toSentenceCase(title)}`; + } + + render() { + return html` +
      + ${this.menuItems.map( + (item) => + html`
    • + ${item.title} +
    • `, + )} +
    + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-primary-nav.test.ts b/src/elements/ia-topnav/ia-topnav-primary-nav.test.ts new file mode 100644 index 00000000..08d1233d --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-primary-nav.test.ts @@ -0,0 +1,136 @@ +import { + elementUpdated, + fixture, + fixtureCleanup, +} from '@open-wc/testing-helpers'; +import { html } from 'lit'; + +import './ia-topnav-primary-nav'; +import { IATopNavConfig, IATopNavSecondIdentitySlotMode } from './models'; +import { PrimaryNav } from './ia-topnav-primary-nav'; + +import { afterEach, describe, expect, test } from 'vitest'; +const component = ({ + baseHost = 'archive.org', + username = '', + screenName = '', + hideSearch = false, + config = {}, + secondIdentitySlotMode = 'allow', +}: { + baseHost?: string; + username?: string; + screenName?: string; + hideSearch?: boolean; + config?: IATopNavConfig; + secondIdentitySlotMode?: IATopNavSecondIdentitySlotMode; +}) => + html` `; + +afterEach(() => { + fixtureCleanup(); +}); + +describe('', () => { + test('renders the login link when no username present', async () => { + const el = await fixture( + component({ + baseHost: 'archive.org', + username: '', + }), + ); + + expect(el.shadowRoot?.querySelector('ia-topnav-login-button')).to.not.be + .undefined; + }); + + test('does not render search trigger or search slot if hideSearch true', async () => { + const el = await fixture( + component({ + baseHost: 'archive.org', + username: 'shaneriley', + screenName: 'shaneriley', + hideSearch: true, + }), + ); + + expect(el.shadowRoot?.querySelector('.search-trigger')).to.equal(null); + expect(el.shadowRoot?.querySelector('.search-container')).to.not.exist; + }); + + test('renders search slot container', async () => { + const el = await fixture( + component({ + baseHost: 'archive.org', + username: 'testuser', + screenName: 'testuser', + }), + ); + + expect(el.shadowRoot?.querySelector('.search-container')).to.exist; + + const slot = el.shadowRoot?.querySelector( + 'slot[name="search"]', + ); + expect(slot).to.exist; + }); + + test('renders search trigger button for mobile toggle', async () => { + const el = await fixture( + component({ + baseHost: 'archive.org', + username: 'testuser', + screenName: 'testuser', + }), + ); + + expect(el.shadowRoot?.querySelector('.search-trigger')).to.exist; + }); + + test('does not render nav-search', async () => { + const el = await fixture( + component({ + baseHost: 'archive.org', + username: 'testuser', + screenName: 'testuser', + }), + ); + + expect(el.shadowRoot?.querySelector('nav-search')).to.not.exist; + }); + + test('opens a slot with `secondIdentitySlotMode`', async () => { + const el = await fixture( + component({ + baseHost: 'archive.org', + username: 'boop', + screenName: 'somesuperlongscreenname', + secondIdentitySlotMode: 'allow', + }), + ); + + const brandingBlock = el.shadowRoot?.querySelector('div.branding'); + expect(brandingBlock?.getAttribute('class')).to.contain( + 'branding second-logo', + ); + + const slot = brandingBlock?.querySelector('slot'); + expect(slot).to.exist; + expect(slot?.getAttribute('name')).to.equal('opt-sec-logo'); + + el.secondIdentitySlotMode = ''; + await elementUpdated(el); + const noSlotBrandingBlock = el.shadowRoot?.querySelector('div.branding'); + expect(noSlotBrandingBlock?.getAttribute('class')).to.contain('branding'); + + const noSlot = noSlotBrandingBlock?.querySelector('slot'); + expect(noSlot).to.not.exist; + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-primary-nav.ts b/src/elements/ia-topnav/ia-topnav-primary-nav.ts new file mode 100644 index 00000000..97b79be1 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-primary-nav.ts @@ -0,0 +1,662 @@ +import { CSSResultGroup, PropertyValues, css, html, nothing } from 'lit'; +import TrackedElement from './tracked-element'; +import icons from './assets/img/icons'; +import './ia-topnav-icon-hamburger'; +import './ia-topnav-login-button'; +import type { LoginButton } from './ia-topnav-login-button'; +import './ia-topnav-media-menu'; +import logoWordmarkStacked from './assets/img/wordmark-stacked'; +import formatUrl from './lib/format-url'; +import { customElement, property, query } from 'lit/decorators.js'; +import { + IATopNavConfig, + IATopNavSecondIdentitySlotMode, + TOPNAV_MOBILE_BREAKPOINT, +} from './models'; +import { defaultTopNavConfig } from './data/menus'; +import themeStyles from '@src/themes/theme-styles'; + +@customElement('ia-topnav-primary-nav') +export class PrimaryNav extends TrackedElement { + @property({ type: String }) mediaBaseHost = 'https://archive.org'; + @property({ type: String }) baseHost = ''; + @property({ type: Boolean }) hideSearch = false; + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + @property({ type: String }) openMenu = ''; + @property({ type: String }) screenName = ''; + @property({ type: String }) + secondIdentitySlotMode: IATopNavSecondIdentitySlotMode = ''; + @property({ type: String }) selectedMenuOption = ''; + @property({ type: Boolean }) signedOutMenuOpen = false; + @property({ type: Boolean }) userMenuOpen = false; + @property({ type: Boolean }) mediaMenuAnimate = false; + @property({ type: String }) username = ''; + @property({ type: String }) userProfileImagePath = ''; + @property({ type: Object }) currentTab: + | { mediatype: string; moveTo: string } + | undefined; + signedOutMenuToggled: unknown; + + @query('button.user-menu') private userMenuButton?: HTMLButtonElement; + @query('ia-topnav-login-button') private loginButton?: HTMLElement; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + button:focus, + input:focus { + outline: none; + } + + nav { + position: relative; + display: flex; + height: 4rem; + grid-template-areas: 'hamburger empty heart search user'; + -ms-grid-columns: 4rem minmax(1rem, 100%) 4rem 4rem 4rem; + grid-template-columns: 4rem auto 4rem 4rem 4rem; + -ms-grid-rows: 100%; + grid-template-rows: 100%; + background: var(--primaryNavBg); + border-bottom: 1px solid var(--primaryNavBottomBorder); + } + + nav.hide-search { + grid-template-areas: 'hamburger empty heart user'; + -ms-grid-columns: 4rem minmax(1rem, 100%) 4rem 4rem; + grid-template-columns: 4rem auto 4rem 4rem; + } + + .right-side-section { + display: flex; + margin-left: auto; + user-select: none; + } + button { + background: none; + color: inherit; + border: none; + font: inherit; + cursor: pointer; + } + + .branding { + position: static; + float: left; + margin: 0 !important; + padding: 0 5px 0 10px; + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0); + } + + slot, + .branding { + display: flex; + justify-content: left; + align-items: center; + } + + ia-topnav-media-menu { + flex: 1; + justify-self: stretch; + } + + .ia-logo { + height: 3rem; + width: 2.7rem; + display: inline-block; + } + .ia-wordmark { + height: 3rem; + width: 9.5rem; + } + .ia-logo, + .ia-wordmark { + margin-right: 5px; + } + + .hamburger { + -ms-grid-row: 1; + -ms-grid-column: 1; + grid-area: hamburger; + padding: 0; + } + .hamburger svg { + height: 4rem; + width: 4rem; + fill: var(--activeColor); + } + + .mobile-donate-link { + display: inline-block; + } + .mobile-donate-link svg { + height: 4rem; + width: 4rem; + } + .mobile-donate-link .fill-color { + fill: rgb(255, 0, 0); + } + + .sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + border: 0; + overflow: hidden; + white-space: nowrap; + clip: rect(1px, 1px, 1px, 1px); + -webkit-clip-path: inset(50%); + clip-path: inset(50%); + user-select: none; + } + + .search-trigger { + padding: 0; + } + .search-trigger svg { + height: 4rem; + width: 4rem; + } + .search-trigger .fill-color { + fill: var(--iconFill); + } + + .search-container { + display: none; + } + + .search-container.open { + display: flex; + position: absolute; + top: 0; + right: 4rem; + bottom: 0; + left: 4rem; + z-index: 3; + padding: 0.5rem; + border-radius: 1rem 1rem 0 0; + background: var(--primaryNavBg); + align-items: center; + animation: fade-in 0.2s forwards; + } + + .search-container ::slotted(*) { + display: block; + } + + .search-container slot { + width: 100%; + } + + @keyframes fade-in { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + + .upload { + display: none; + } + + .upload span { + display: none; + } + + .upload svg { + height: 3rem; + width: 3rem; + } + + .screen-name { + display: none; + font-size: 1.3rem; + vertical-align: middle; + text-transform: uppercase; + } + + .user-menu { + color: var(--lightTextColor); + padding: 0.5rem; + height: 100%; + } + + button.user-menu:hover, + button.user-menu:focus { + color: var(--linkHoverColor); + outline: none; + } + + .user-menu.active { + border-radius: 1rem 1rem 0 0; + background: var(--activeButtonBg); + } + + .user-menu img { + display: block; + width: 3rem; + height: 3rem; + } + + .link-home { + text-decoration: none; + display: inline-flex; + } + a.link-home:focus, + a.link-home:focus-visible { + outline-offset: 1px; + } + + @media only screen and (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) and (max-device-width: 905px) { + .branding.second-logo { + padding-right: 0; + } + } + + @media (min-width: 906px) { + .branding.second-logo { + padding-right: 20px; + } + } + + @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { + slot[name='opt-sec-logo'] { + display: none; + } + + .right-side-section { + display: initial; + } + .right-side-section .user-info { + float: right; + } + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + :host { + --userIconWidth: 3.2rem; + --userIconHeight: 3.2rem; + } + + nav { + display: flex; + z-index: 4; + height: 5rem; + padding-right: 1.5rem; + } + + slot[name='opt-sec-logo-mobile'] { + display: none; + } + + .ia-logo, + .ia-wordmark { + margin-right: 10px; + } + + .hamburger, + .search-trigger, + .mobile-donate-link { + display: none; + } + + .user-info { + display: block; + float: right; + vertical-align: middle; + height: 100%; + } + + .user-info .user-menu img { + height: 3rem; + width: 3rem; + margin-right: 0.5rem; + } + + .user-menu { + padding: 1rem 0.5rem; + } + .user-menu.active { + background: transparent; + } + + .user-menu img { + display: inline-block; + vertical-align: middle; + margin-right: 0.5rem; + } + + .upload { + display: block; + padding: 1rem 0.5rem; + float: right; + font-size: 1.4rem; + text-transform: uppercase; + text-decoration: none; + color: var(--lightTextColor); + } + .upload:active, + .upload:focus, + .upload:hover { + color: var(--linkHoverColor); + } + .upload:focus-visible { + outline: none; + } + + .upload svg { + vertical-align: middle; + fill: var(--iconFill); + } + + .upload:hover svg, + .upload:focus svg, + .upload:active svg { + fill: var(--linkHoverColor); + } + + .search-container, + .search-container.open { + display: flex; + position: static; + top: auto; + right: auto; + bottom: auto; + left: auto; + align-items: center; + padding: 0 0 0 1rem; + background: transparent; + border-radius: 0; + z-index: auto; + } + + .search-container slot { + width: auto; + } + } + + @media (min-width: 990px) { + .screen-name { + display: inline-block; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + max-width: 165px; + } + + .upload span { + display: inline-block; + vertical-align: middle; + } + } + `, + ]; + } + + /** Distance (px) from this element's right edge to the right edge of the account dropdown toggle. */ + getAccountDropdownOffset(): number { + const hostRect = this.getBoundingClientRect(); + + if (this.userMenuButton) { + return hostRect.right - this.userMenuButton.getBoundingClientRect().right; + } + + if (this.loginButton) { + const loginRect = this.loginButton.getBoundingClientRect(); + const innerOffset = ( + this.loginButton as LoginButton + ).getDropdownToggleOffset(); + return hostRect.right - loginRect.right + innerOffset; + } + + return 0; + } + + toggleMediaMenu(e: Event) { + this.trackClick(e); + this.dispatchEvent( + new CustomEvent('menuToggled', { + detail: { + menuName: 'media', + }, + }), + ); + } + + toggleSearchMenu(e: Event) { + this.trackClick(e); + this.dispatchEvent( + new CustomEvent('menuToggled', { + detail: { + menuName: 'search', + }, + }), + ); + } + + toggleUserMenu(e: Event) { + this.trackClick(e); + this.dispatchEvent( + new CustomEvent('menuToggled', { + detail: { + menuName: 'user', + }, + }), + ); + } + + updated(props: PropertyValues) { + if (props.has('currentTab')) { + // early return + if (!this.currentTab || Object.keys(this.currentTab).length === 0) + return nothing; + + const isUserMenuTab = + this.currentTab && this.currentTab.mediatype === 'usermenu'; + if (isUserMenuTab) { + const mediaButtons = Array.from( + this.shadowRoot + ?.querySelector('ia-topnav-media-menu') + ?.shadowRoot?.querySelectorAll('ia-topnav-media-button') ?? [], + ); + const lastMediaButton = mediaButtons.filter((element) => { + return element.shadowRoot + ?.querySelector('a') + ?.classList.contains('images'); + }); + + let nextElement; + if (this.username) { + nextElement = this.shadowRoot?.querySelector('a.upload'); + } else { + nextElement = this.shadowRoot + ?.querySelector('ia-topnav-login-button') + ?.shadowRoot?.querySelector('span a'); + } + + const menuItemElement = + lastMediaButton[0]?.shadowRoot?.querySelector('a.menu-item'); + + const focusElement = + this.currentTab.moveTo === 'next' ? nextElement : menuItemElement; + + if (focusElement) { + (focusElement as HTMLElement).focus(); + } + } else if (this.currentTab.moveTo === 'next') { + if (this.shadowRoot?.querySelector('.user-menu')) { + (this.shadowRoot?.querySelector('.user-menu') as HTMLElement).focus(); + } else { + ( + this.shadowRoot + ?.querySelector('ia-topnav-login-button') + ?.shadowRoot?.querySelectorAll('span a')[0] as HTMLElement + )?.focus(); + } + } + } + } + + get userIcon() { + const userMenuClass = this.openMenu === 'user' ? 'active' : ''; + const userMenuToolTip = + this.openMenu === 'user' ? 'Close user menu' : 'Expand user menu'; + + return html` + + `; + } + + get loginIcon() { + return html` + + `; + } + + get searchMenuOpen() { + return this.openMenu === 'search'; + } + + get allowSecondaryIcon() { + return this.secondIdentitySlotMode === 'allow'; + } + + /** + * The search slot container, rendered between ia-topnav-media-menu and + * right-side-section so it sits left of the Upload button on desktop. + */ + get searchSlotContainer() { + if (this.hideSearch) return nothing; + return html` +
    + +
    + `; + } + + get searchMenu() { + if (this.hideSearch) return nothing; + + return html` + + `; + } + + get mobileDonateHeart() { + return html` + + ${icons.donateUnpadded} + "Donate to the archive" + + `; + } + + get uploadButtonTemplate() { + return html` + ${icons.upload} + Upload + `; + } + + get userStateTemplate() { + return html``; + } + + get secondLogoSlot() { + return this.allowSecondaryIcon + ? html` + + + ` + : nothing; + } + + get secondLogoClass() { + return this.allowSecondaryIcon ? 'second-logo' : ''; + } + + render() { + // const mediaMenuTabIndex = this.openMenu === 'media' ? '' : '-1'; + return html` + + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-save-page-form.test.ts b/src/elements/ia-topnav/ia-topnav-save-page-form.test.ts new file mode 100644 index 00000000..95e50828 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-save-page-form.test.ts @@ -0,0 +1,47 @@ +import { fixture } from '@open-wc/testing-helpers'; +import { html } from 'lit'; +import { describe, expect, test } from 'vitest'; + +import './ia-topnav-save-page-form'; +import type { SavePageForm } from './ia-topnav-save-page-form'; + +const component = html``; + +/** + * Submits the form for real rather than calling the private handler. The + * submit is cancelable and the handler calls `preventDefault()` on an invalid + * URL, so nothing navigates either way. + */ +async function submitWith(el: SavePageForm, url: string): Promise { + const form = el.shadowRoot?.querySelector('form') as HTMLFormElement; + const urlInput = form.querySelector( + '[name="url_preload"]', + ) as HTMLInputElement; + urlInput.value = url; + form.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true })); + await el.updateComplete; +} + +describe('', () => { + test('rejects a URL with no domain suffix and shows the error', async () => { + const el = await fixture(component); + + await submitWith(el, 'archive'); + + expect(el.inputValid).to.be.false; + expect(el.shadowRoot?.querySelector('.error')?.className).to.contain( + 'visible', + ); + }); + + test('accepts a URL with a domain suffix and hides the error', async () => { + const el = await fixture(component); + + await submitWith(el, 'archive.org'); + + expect(el.inputValid).to.be.true; + expect(el.shadowRoot?.querySelector('.error')?.className).to.not.contain( + 'visible', + ); + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-save-page-form.ts b/src/elements/ia-topnav/ia-topnav-save-page-form.ts new file mode 100644 index 00000000..6523330f --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-save-page-form.ts @@ -0,0 +1,121 @@ +import { CSSResultGroup, css, html } from 'lit'; +import TrackedElement from './tracked-element'; +import { customElement, property, state } from 'lit/decorators.js'; +import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; +import { defaultTopNavConfig } from './data/menus'; +import themeStyles from '@src/themes/theme-styles'; +import { srOnlyStyles } from '@src/themes/sr-only-styles'; + +@customElement('ia-topnav-save-page-form') +export class SavePageForm extends TrackedElement { + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + + @state() inputValid = true; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + div { + display: grid; + grid-template-columns: 1fr auto; + grid-column-gap: 0.8rem; + margin: 0; + padding: 0; + border: none; + } + + input[type='text'] { + width: 100%; + height: 3rem; + box-sizing: border-box; + border: 1px solid var(--savePageInputBorder); + border-radius: 0.5rem; + color: var(--grey13); + font-size: inherit; + } + + input[type='submit'] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 0.4rem 0.8rem; + font: normal 1.3rem var(--themeFontFamily); + text-transform: uppercase; + color: var(--savePageSubmitText); + border: none; + border-radius: 16px; + background: var(--savePageSubmitBg); + cursor: pointer; + } + + .error { + display: none; + margin-top: 0.5rem; + font-weight: bold; + color: var(--savePageErrorText); + } + + .visible { + display: block; + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + h3 { + margin-top: 0; + font: normal 100 1.6rem var(--themeFontFamily); + } + } + `, + srOnlyStyles, + ]; + } + + private validateURL(e: SubmitEvent) { + const target = e.target as HTMLFormElement; + const urlInput = target.querySelector( + '[name="url_preload"]', + ) as HTMLInputElement; + const valid = /\..{2,}$/.test(urlInput.value); + + if (!valid) { + e.preventDefault(); + this.inputValid = false; + return; + } + this.inputValid = true; + this.trackSubmit(e); + } + + get errorClass() { + return `error${this.inputValid ? '' : ' visible'}`; + } + + render() { + return html` +
    +

    Save Page Now

    +

    + Capture a web page as it appears now for use as a trusted citation in + the future. +

    +
    + + + +
    +

    Please enter a valid web address

    +
    + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-signed-out-dropdown.ts b/src/elements/ia-topnav/ia-topnav-signed-out-dropdown.ts new file mode 100644 index 00000000..9f08e954 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-signed-out-dropdown.ts @@ -0,0 +1,5 @@ +import { customElement } from 'lit/decorators.js'; +import DropdownMenu from './dropdown-menu'; + +@customElement('ia-topnav-signed-out-dropdown') +export class SignedOutDropdown extends DropdownMenu {} diff --git a/src/elements/ia-topnav/ia-topnav-story.ts b/src/elements/ia-topnav/ia-topnav-story.ts new file mode 100644 index 00000000..04b71cbf --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-story.ts @@ -0,0 +1,156 @@ +import { css, html, LitElement, type CSSResultGroup } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; + +import './ia-topnav'; +import type { PropInputSettings } from '@demo/story-components/story-prop-settings'; +import '@demo/story-template'; + +import type { IATopNav } from './ia-topnav'; + +/** + * Enough of an item to exercise the admin sections of the user menu. Biblio + * has to arrive with a query string already on it, since the identifier is + * appended to it. + */ +const DEMO_ITEM_IDENTIFIER = 'goody'; +const DEMO_UPLOADER = 'uploader@archive.org'; +const DEMO_BIBLIO = 'https://openlibrary.org/search/inside?q='; + +@customElement('ia-topnav-story') +export class IATopNavStory extends LitElement { + @state() private signedIn = false; + + @state() private onAnItem = false; + + @state() private admin = false; + + @state() private canManageFlags = false; + + @state() private hideSearch = false; + + @state() private lastEvent = ''; + + private get propInputData() { + const settings: PropInputSettings[] = [ + { + label: 'Wayback pages archived', + propertyName: 'waybackPagesArchived', + defaultValue: '916 billion', + }, + ]; + return { settings }; + } + + private onAnalyticsClick(e: CustomEvent): void { + this.lastEvent = `analyticsClick → ${e.detail?.event ?? ''}`; + } + + private onAnalyticsSubmit(e: CustomEvent): void { + this.lastEvent = `analyticsSubmit → ${e.detail?.event ?? ''}`; + } + + private toggleRow( + label: string, + key: 'signedIn' | 'onAnItem' | 'admin' | 'canManageFlags' | 'hideSearch', + ) { + return html` + + ${label} + + { + this[key] = !this[key]; + }} + /> + + + `; + } + + render() { + const username = this.signedIn ? 'brewster' : ''; + const screenName = this.signedIn ? 'Brewster' : ''; + const itemIdentifier = this.onAnItem ? DEMO_ITEM_IDENTIFIER : ''; + const uploader = this.onAnItem && this.admin ? DEMO_UPLOADER : ''; + const biblio = this.onAnItem && this.admin ? DEMO_BIBLIO : ''; + + return html` + +
    + +

    ${this.lastEvent || 'No events yet.'}

    +
    + +
    + + ${this.toggleRow('Signed in', 'signedIn')} + ${this.toggleRow('Viewing an item', 'onAnItem')} + ${this.toggleRow('Admin on the item', 'admin')} + ${this.toggleRow('Can manage flags', 'canManageFlags')} + ${this.toggleRow('Hide search', 'hideSearch')} +
    +

    + The admin sections of the user menu need all three of Signed in, + Viewing an item and Admin on the item. Narrow the window below 890px + for the mobile layout. +

    +
    + +
    +

    + The topnav renders the whole archive.org masthead: the primary nav, + the media menu and its slider, the wayback search, and the account + dropdown. It reports clicks and form submits through + analyticsClick and analyticsSubmit rather + than talking to an analytics service itself. +

    +

    + The user menu grows an admin section when + itemIdentifier and admin are both set. + Setting uploader adds the uploader's account links, and + biblio adds the book-scanning links for a texts item. +

    +

    + A search bar goes in the search slot. Offshoot slots an + ia-dropdown-search-bar in there. +

    +
    +
    + `; + } + + static get styles(): CSSResultGroup { + return css` + .event-log { + margin: 0.8rem 0 0; + font-family: monospace; + font-size: 1.2rem; + } + + .hint { + font-size: 1.2rem; + } + + td { + padding-right: 1rem; + } + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-user-menu.test.ts b/src/elements/ia-topnav/ia-topnav-user-menu.test.ts new file mode 100644 index 00000000..1190194a --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-user-menu.test.ts @@ -0,0 +1,38 @@ +import { fixture } from '@open-wc/testing-helpers'; +import { html } from 'lit'; +import './ia-topnav-user-menu'; +import { buildTopNavMenus } from './data/menus'; +import UserMenu from './ia-topnav-user-menu'; + +import { describe, expect, test } from 'vitest'; +const component = html``; +const component2 = html``; + +describe('', () => { + test('does not render admin links for logged out users', async () => { + const el = await fixture(component); + el.menuItems = buildTopNavMenus().user; + + await el.updateComplete; + + expect(el.shadowRoot?.querySelectorAll('li').length).to.be.gt(0); + expect(el.shadowRoot?.querySelectorAll('.divider').length).to.equal(0); + }); + + test('does not render admin links for logged in users', async () => { + // NOTE: top-nav never renders admin links now -- that's been delegated to dynamic JS insertion + // in petabox tree (since it's only relevant there). + const el = await fixture(component2); + el.menuItems = buildTopNavMenus('brewster_userid').user; + + await el.updateComplete; + + expect(el.shadowRoot?.querySelectorAll('li').length).to.be.gt(0); + expect(el.shadowRoot?.querySelectorAll('.divider').length).to.equal(0); + + expect(el.shadowRoot?.querySelectorAll('h3').length).to.equal(1); + expect(el.shadowRoot?.querySelector('h3')?.innerText).to.equal('brewster'); + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-user-menu.ts b/src/elements/ia-topnav/ia-topnav-user-menu.ts new file mode 100644 index 00000000..f8ce6b40 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-user-menu.ts @@ -0,0 +1,26 @@ +import { html } from 'lit'; +import DropdownMenu from './dropdown-menu'; +import { customElement, property } from 'lit/decorators.js'; + +@customElement('ia-topnav-user-menu') +export default class UserMenu extends DropdownMenu { + @property({ type: String }) username = ''; + @property({ type: String }) screenName = ''; + + render() { + return html` + + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav-wayback-search.ts b/src/elements/ia-topnav/ia-topnav-wayback-search.ts new file mode 100644 index 00000000..a9cb7de3 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-wayback-search.ts @@ -0,0 +1,273 @@ +import { css, CSSResultGroup, LitElement, html } from 'lit'; +import { customElement, property, query } from 'lit/decorators.js'; + +import searchIcon from './assets/img/icon-search'; +import logo from './assets/img/wayback-logo'; +import { TOPNAV_MOBILE_BREAKPOINT } from './models'; +import themeStyles from '@src/themes/theme-styles'; +import { srOnlyStyles } from '@src/themes/sr-only-styles'; + +/** + * The Wayback Machine search form shown inside the topnav's wayback slider. + * + * The layout rules the topnav needs sit in the last `css` block so they win + * over the base ones on equal specificity. + */ +@customElement('ia-topnav-wayback-search') +export class IATopNavWaybackSearch extends LitElement { + @property({ type: Object }) queryHandler: { + performQuery: (query: string) => void; + } = { + performQuery: (query: string) => + (window.location.href = `https://web.archive.org/web/*/${query}`), + }; + + @property({ type: String }) waybackPagesArchived = '916 billion'; + + @query('#url') private urlInput!: HTMLInputElement; + + render() { + return html` +
    +

    + Search the history of more than ${this.waybackPagesArchived} + web pages + on the Internet. +

    +
    + ${logo} +
    + + + ${searchIcon} +
    +
    +
    + `; + } + + handleSubmit(e: Event) { + e.preventDefault(); + const query = this.urlInput.value; + this.emitWaybackSearchSubmitted(query); + this.queryHandler.performQuery(query); + } + + emitWaybackSearchSubmitted(query: string) { + this.dispatchEvent( + new CustomEvent('waybackSearchSubmitted', { + detail: { + query, + }, + }), + ); + } + + emitWaybackMachineStatsLinkClicked() { + this.dispatchEvent(new CustomEvent('waybackMachineStatsLinkClicked')); + } + + emitWaybackMachineLogoLinkClicked() { + this.dispatchEvent(new CustomEvent('waybackMachineLogoLink')); + } + + static styles: CSSResultGroup = [ + themeStyles, + srOnlyStyles, + css` + :host { + --topnav-wayback-input-text-color--: var( + --ia-theme-secondary-text-color, + #666 + ); + --topnav-wayback-input-bg--: var( + --ia-theme-secondary-background-color, + #fff + ); + /* + * The desktop icon had no fallback when this lived in its own package + * and nothing has ever set it, so the fill resolved to invalid and the + * glyph painted black against the dark nav. It follows the topnav's + * icon color now. + */ + --topnav-wayback-desktop-icon-fill--: var( + --desktopSearchIconFill, + var(--iconFill) + ); + + font: normal 1.2rem/1.5 var(--themeFontFamily); + } + + form { + max-width: 600px; + } + + p { + margin-top: 0; + font-weight: 200; + } + + a { + font-weight: 500; + text-decoration: none; + color: var(--activeColor); + } + + fieldset { + padding: 0.7rem 2rem; + margin: 1.5rem 0; + box-sizing: border-box; + text-align: center; + border: none; + border-radius: 7px; + background-color: #fcf5e6; + box-shadow: 3px 3px 0 0 #c3ad97; + } + + fieldset a { + font-size: 0; + } + + img { + width: 100%; + max-width: 215px; + max-height: 60px; + margin-bottom: 1.3rem; + vertical-align: middle; + } + + input { + display: block; + width: 100%; + height: 3rem; + padding: 0.5rem 1rem 0.5rem 3rem; + font: normal 1.2rem/1.5 var(--themeFontFamily); + color: var(--topnav-wayback-input-text-color--); + box-sizing: border-box; + border: 1px solid var(--grey80); + border-radius: 2rem; + background: var(--topnav-wayback-input-bg--); + } + + input:focus { + border-color: #66afe9; + outline: none; + } + + .search-field { + position: relative; + overflow: hidden; + } + + .search-field svg { + position: absolute; + top: 3px; + left: 3px; + width: 2.4rem; + height: 2.4rem; + } + + .search-field .fill-color { + fill: var(--iconFill); + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + form { + margin: 0 auto; + } + + p { + margin-bottom: 3rem; + font-size: 1.6rem; + text-align: center; + } + + img { + margin: 0; + } + + fieldset { + margin: 0 auto; + } + + fieldset a, + .search-field { + display: inline-block; + width: 49%; + vertical-align: middle; + } + + fieldset a { + text-align: center; + } + + .search-field svg { + top: 2px; + } + + .search-field .fill-color { + fill: var(--topnav-wayback-desktop-icon-fill--); + } + } + `, + css` + p { + margin-bottom: 1rem; + font-size: 1.6rem; + text-align: center; + } + + fieldset { + padding: 0.5rem; + border-radius: 5px; + box-shadow: none; + } + + input { + padding-left: 3rem; + margin-top: 0.3rem; + font-size: 1.4rem; + border-color: #bca38e; + background: #fff; + } + + input::placeholder, + input::-webkit-input-placeholder { + color: #8e8e8e; + } + + .search-field svg { + top: 50%; + transform: translateY(-50%); + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + fieldset a, + .search-field { + display: block; + width: auto; + } + + fieldset a { + margin: 0 1.5rem; + } + } + `, + ]; +} diff --git a/src/elements/ia-topnav/ia-topnav-wayback-slider.test.ts b/src/elements/ia-topnav/ia-topnav-wayback-slider.test.ts new file mode 100644 index 00000000..b54483ee --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-wayback-slider.test.ts @@ -0,0 +1,99 @@ +import { fixture } from '@open-wc/testing-helpers'; +import { html } from 'lit'; + +import './ia-topnav-wayback-slider'; +import type { IATopNavLink } from './models'; + +import { describe, expect, test } from 'vitest'; +const component = ({ + archiveItLinks, + browserExtensionsLinks, + config, + mobileAppsLinks, +}: { + archiveItLinks: IATopNavLink[]; + browserExtensionsLinks: IATopNavLink[]; + config: Record; + mobileAppsLinks: IATopNavLink[]; +}) => html` + +`; + +const buildDefaults = () => ({ + config: {}, + archiveItLinks: [ + { + url: '1', + title: 'first', + }, + { + url: '2', + title: 'second', + }, + ], + browserExtensionsLinks: [ + { + url: '3', + title: 'third', + }, + { + url: '4', + title: 'fourth', + }, + ], + mobileAppsLinks: [ + { + url: '5', + title: 'fifth', + }, + { + url: '6', + title: 'sixth', + }, + ], +}); + +describe('', () => { + test('renders the links passed in via the archiveItLinks prop', async () => { + const options = buildDefaults(); + const el = await fixture(component(options)); + const anchors = el.shadowRoot?.querySelectorAll('.archive-it a') ?? []; + + options.archiveItLinks.forEach((link, i) => { + const anchor = anchors[i] as HTMLAnchorElement; + expect(anchor.innerText).to.equal(link.title); + expect(anchor.getAttribute('href')).to.contain(link.url); + }); + }); + + test('renders the links passed in via the browserExtensionsLinks prop', async () => { + const options = buildDefaults(); + const el = await fixture(component(options)); + const anchors = + el.shadowRoot?.querySelectorAll('.browser-extensions a') ?? []; + + options.browserExtensionsLinks.forEach((link, i) => { + const anchor = anchors[i] as HTMLAnchorElement; + expect(anchor.innerText).to.equal(link.title); + expect(anchor.getAttribute('href')).to.contain(link.url); + }); + }); + + test('renders the links passed in via the mobileAppsLinks prop', async () => { + const options = buildDefaults(); + const el = await fixture(component(options)); + const anchors = el.shadowRoot?.querySelectorAll('.mobile-apps a') ?? []; + + options.mobileAppsLinks.forEach((link, i) => { + const anchor = anchors[i] as HTMLAnchorElement; + expect(anchor.innerText).to.equal(link.title); + expect(anchor.getAttribute('href')).to.contain(link.url); + }); + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav-wayback-slider.ts b/src/elements/ia-topnav/ia-topnav-wayback-slider.ts new file mode 100644 index 00000000..0edd6dc0 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav-wayback-slider.ts @@ -0,0 +1,125 @@ +import { CSSResultGroup, css, html } from 'lit'; +import './ia-topnav-wayback-search'; +import TrackedElement from './tracked-element'; +import './ia-topnav-save-page-form'; +import queryHandler from './lib/query-handler'; +import toSentenceCase from './lib/t-sentence-case'; +import formatUrl from './lib/format-url'; +import { customElement, property } from 'lit/decorators.js'; +import { + IATopNavConfig, + IATopNavLink, + TOPNAV_MOBILE_BREAKPOINT, +} from './models'; +import { defaultTopNavConfig } from './data/menus'; +import { subnavListCSS } from './subnav-list-styles'; +import themeStyles from '@src/themes/theme-styles'; + +@customElement('ia-topnav-wayback-slider') +export class WaybackSlider extends TrackedElement { + @property({ type: Array }) archiveItLinks: IATopNavLink[] = []; + @property({ type: String }) baseHost = ''; + @property({ type: Array }) browserExtensionsLinks: IATopNavLink[] = []; + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + @property({ type: Array }) mobileAppsLinks: IATopNavLink[] = []; + + static get styles(): CSSResultGroup { + return [ + themeStyles, + subnavListCSS, + css` + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + :host { + display: block; + grid-column: 1 / 4; + padding: 0 1.5rem; + } + + h4 { + margin-top: 0; + font: normal 100 1.6rem var(--themeFontFamily); + } + + .grid { + display: grid; + grid-template-columns: minmax(auto, 260px) 1fr minmax(auto, 260px); + /* Possible for 890 - 935: minmax(auto, 260px) 1fr minmax(auto, 260px) */ + grid-column-gap: 2.5rem; + } + + .link-lists { + display: grid; + grid-template-columns: calc(50% - 1.25rem) calc(50% - 1.25rem); + grid-column-gap: 2.5rem; + } + } + `, + ]; + } + + get mobileAppsItems() { + return this.linkList(this.mobileAppsLinks, 'Wayback'); + } + + get browserExtensionsItems() { + return this.linkList(this.browserExtensionsLinks, 'Wayback'); + } + + get archiveItItems() { + return this.linkList(this.archiveItLinks, 'ArchiveIt'); + } + + private linkList(links: IATopNavLink[], eventPrefix: string) { + return links.map( + (link) => + html`
  • + ${link.title} +
  • `, + ); + } + + analyticsEvent(title: string) { + return `${this.config?.eventCategory}|${toSentenceCase(title)}`; + } + + render() { + return html` +
    + + + +
    + `; + } +} diff --git a/src/elements/ia-topnav/ia-topnav.test.ts b/src/elements/ia-topnav/ia-topnav.test.ts new file mode 100644 index 00000000..569d66d9 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav.test.ts @@ -0,0 +1,393 @@ +import { + elementUpdated, + fixture, + fixtureCleanup, + oneEvent, +} from '@open-wc/testing-helpers'; +import { html } from 'lit'; + +import './ia-topnav'; +import { IATopNav } from './ia-topnav'; +import { SignedOutDropdown } from './ia-topnav-signed-out-dropdown'; +import UserMenu from './ia-topnav-user-menu'; + +import { afterEach, describe, expect, test } from 'vitest'; +const verifyClosed = (instance: IATopNav) => { + expect(instance.mediaSliderOpen).to.be.false; + expect(instance.selectedMenuOption).to.equal(''); +}; + +const verifyOpened = (instance: IATopNav, mediatype: string) => { + expect(instance.mediaSliderOpen).to.be.true; + expect(instance.selectedMenuOption).to.equal(mediatype); +}; + +afterEach(() => { + fixtureCleanup(); +}); + +describe('', () => { + test('dispatches an analyticsClick event when trackClick event fired', async () => { + const el = await fixture(html` `); + const clickEvent = new MouseEvent('click'); + + setTimeout(() => + el.shadowRoot + ?.querySelector('ia-topnav-primary-nav') + ?.shadowRoot?.querySelector('.hamburger') + ?.dispatchEvent(clickEvent), + ); + const response = await oneEvent(el, 'trackClick'); + + expect(response).to.exist; + }); + + test('closes all menus when close-layer clicked', async () => { + const el = await fixture(html` `); + + el.openMenu = 'media'; + el.selectedMenuOption = 'texts'; + el.mediaSliderOpen = true; + await el.updateComplete; + el.closeMenus(); + await el.updateComplete; + + expect(el.mediaSliderOpen).to.be.false; + expect(el.openMenu).to.equal(''); + expect(el.selectedMenuOption).to.equal(''); + }); + + test('sets media slider to closed', async () => { + const el = await fixture(html` `); + + el.mediaSliderOpen = true; + el.selectedMenuOption = 'foo'; + el.closeMediaSlider(); + + verifyClosed(el); + }); + + test('toggles media slider visibility and starts animation', async () => { + const el = await fixture(html` `); + const mediatype = 'foo'; + + el.selectedMenuOption = mediatype; + el.openMediaSlider(); + + verifyOpened(el, mediatype); + }); + + test('closes media slider if selected menu type is the open menu type', async () => { + const el = await fixture(html` `); + const mediatype = 'foo'; + + el.selectedMenuOption = mediatype; + + const event = new CustomEvent('mediaTypeSelected', { + detail: { + mediatype, + }, + }); + + el.mediaTypeSelected(event); + + verifyClosed(el); + }); + + test('opens media slider menu and starts animation', async () => { + const el = await fixture(html` `); + const mediatype = 'foo'; + + const event = new CustomEvent('mediaTypeSelected', { + detail: { + mediatype, + }, + }); + + el.mediaTypeSelected(event); + + verifyOpened(el, mediatype); + }); + + test('closes slider when menu closed', async () => { + const el = await fixture(html` `); + + el.openMenu = 'media'; + el.selectedMenuOption = 'foo'; + el.mediaSliderOpen = true; + await el.updateComplete; + + const event = new CustomEvent('menuToggled', { + detail: { + menuName: '', + }, + }); + + el.menuToggled(event); + await el.updateComplete; + + expect(el.selectedMenuOption).to.equal(''); + }); + + test('toggles user menu tabindex when dropdown open', async () => { + const el = await fixture( + html` `, + ); + + el.openMenu = 'user'; + await el.updateComplete; + + expect( + el.shadowRoot + ?.querySelector('ia-topnav-user-menu') + ?.getAttribute('tabindex'), + ).to.equal(''); + }); + + test('toggles signed out menu tabindex when dropdown open', async () => { + const el = await fixture(html` `); + + el.openMenu = 'login'; + await el.updateComplete; + + expect( + el.shadowRoot + ?.querySelector('ia-topnav-signed-out-dropdown') + ?.getAttribute('tabindex'), + ).to.equal(''); + }); + + test('toggles search menu when search toggle button clicked', async () => { + const el = await fixture(html` `); + ( + el.shadowRoot + ?.querySelector('ia-topnav-primary-nav') + ?.shadowRoot?.querySelector('.search-trigger') as HTMLButtonElement + ).click(); + await el.updateComplete; + + expect(el.openMenu).to.equal('search'); + }); + + test('toggles user menu when search user avatar clicked', async () => { + const el = await fixture( + html` `, + ); + + ( + el.shadowRoot + ?.querySelector('ia-topnav-primary-nav') + ?.shadowRoot?.querySelector('.user-menu') as HTMLButtonElement + ).click(); + await el.updateComplete; + + expect(el.openMenu).to.equal('user'); + }); + + test('uses localLinks for archive.org logo link', async () => { + const el = await fixture( + html` `, + ); + const logoLink = el.shadowRoot + ?.querySelector('ia-topnav-primary-nav') + ?.shadowRoot?.querySelector('.link-home'); + expect(logoLink?.getAttribute('href')).to.match(/\/\/archive\.org/); + }); + + describe('sets localLinks properly', async () => { + test('uses localLinks to archive.org links on common child components', async () => { + const el = await fixture( + html` `, + ); + const componentSelectors = [ + 'ia-topnav-primary-nav', + 'ia-topnav-media-slider', + 'ia-topnav-desktop-subnav', + ]; + componentSelectors.forEach((selector) => { + const component = el.shadowRoot?.querySelector(selector) as unknown as { + baseHost: string; + }; + expect(component?.baseHost).to.equal('https://archive.org'); + }); + }); + + test('uses localLinks to archive.org links on the signed out dropdown', async () => { + const el = await fixture( + html` `, + ); + const signedOutDropdown = el.shadowRoot?.querySelector( + 'ia-topnav-signed-out-dropdown', + ) as SignedOutDropdown; + expect(signedOutDropdown?.baseHost).to.equal('https://archive.org'); + }); + + test('uses localLinks to archive.org links on the user dropdown', async () => { + const el = await fixture( + html` `, + ); + const signedOutDropdown = el.shadowRoot?.querySelector( + 'ia-topnav-user-menu', + ) as UserMenu; + expect(signedOutDropdown.baseHost).to.equal('https://archive.org'); + }); + }); + + describe('search slot', () => { + test('forwards search slot to ia-topnav-primary-nav', async () => { + const el = await fixture(html``); + await el.updateComplete; + + const primaryNav = el.shadowRoot?.querySelector('ia-topnav-primary-nav'); + const slot = primaryNav?.querySelector('slot[name="search"]'); + expect(slot).to.exist; + }); + + test('does not render search-menu', async () => { + const el = await fixture(html``); + await el.updateComplete; + + expect(el.shadowRoot?.querySelector('search-menu')).to.not.exist; + }); + }); + + describe('slot pass throughs', () => { + describe('slot for ', () => { + test('opens a slot with `secondIdentitySlotMode`', async () => { + const el = await fixture( + html``, + ); + + const slot = el.shadowRoot + ?.querySelector('ia-topnav-primary-nav') + ?.querySelector('slot[name="opt-sec-logo"]'); + expect(slot).to.exist; + + el.secondIdentitySlotMode = ''; + await elementUpdated(el); + const noSlot = el.shadowRoot + ?.querySelector('ia-topnav-primary-nav') + ?.querySelector('slot[name="opt-sec-logo"]'); + expect(noSlot).to.not.exist; + }); + }); + }); +}); + +describe(' admin user menu sections', () => { + type ExtraSection = '' | 'uploader' | 'biblio' | 'both'; + const adminFixture = async (extra: ExtraSection = '') => + fixture( + html``, + ); + + test('renders the basic and item admin sections by default', async () => { + const el = await adminFixture(); + expect(el.userMenuItems.length).to.equal(2); + }); + + test('adds an uploader section when an uploader is set', async () => { + const el = await adminFixture('uploader'); + const sections = el.userMenuItems; + expect(sections.length).to.equal(3); + + const uploaderSection = sections[2]; + expect(uploaderSection.map((link) => link.title)).to.deep.equal([ + 'uploader:', + 'up+loader@example.com', + 'user admin', + 'user privs', + ]); + expect(uploaderSection[0].url).to.be.undefined; + expect(uploaderSection[1].url).to.be.undefined; + expect(uploaderSection[2].url).to.equal( + 'https://catalogd.archive.org/control/useradmin.php?email=up%2Bloader%40example.com', + ); + expect(uploaderSection[3].url).to.equal( + 'https://catalogd.archive.org/control/setadmin.php?user=up%2Bloader%40example.com&ignore=boop', + ); + }); + + test('adds a biblio section when a biblio URL is set', async () => { + const el = await adminFixture('biblio'); + const sections = el.userMenuItems; + expect(sections.length).to.equal(3); + + const biblioSection = sections[2]; + expect(biblioSection.map((link) => link.title)).to.deep.equal([ + 'biblio', + 'bookview', + 'jp2 zip', + ]); + expect(biblioSection[0].url).to.equal( + 'https://books-yaz.archive.org/biblio.php?b_id=boop&add=1&ignored=boop', + ); + expect(biblioSection[1].url).to.equal( + 'https://archive.org/bookview.php?mode=debug&identifier=boop', + ); + expect(biblioSection[2].url).to.equal( + 'https://archive.org/download/boop/format=Single Page Processed JP2 ZIP', + ); + }); + + test('orders the biblio section before the uploader section', async () => { + const el = await adminFixture('both'); + const sections = el.userMenuItems; + expect(sections.length).to.equal(4); + expect(sections[2][0].title).to.equal('biblio'); + expect(sections[3][0].title).to.equal('uploader:'); + }); + + test('renders the sections in the user menu with dividers between them', async () => { + const el = await adminFixture('both'); + // The menus rebuild in updated(), so the sections land one update later. + await el.updateComplete; + const userMenu = el.shadowRoot?.querySelector( + 'ia-topnav-user-menu', + ) as UserMenu; + await userMenu.updateComplete; + + const listItems = Array.from( + userMenu.shadowRoot?.querySelectorAll('li') ?? [], + ); + const text = listItems.map((li) => li.textContent?.trim()); + expect(text).to.include('uploader:'); + expect(text).to.include('up+loader@example.com'); + expect(text).to.include('user privs'); + expect(text).to.include('jp2 zip'); + expect(userMenu.shadowRoot?.querySelectorAll('.divider').length).to.equal( + 3, + ); + }); + + test('leaves the extra sections out for non-admins', async () => { + const el = await fixture( + html``, + ); + expect(el.userMenuItems.length).to.equal(1); + }); +}); diff --git a/src/elements/ia-topnav/ia-topnav.ts b/src/elements/ia-topnav/ia-topnav.ts new file mode 100644 index 00000000..58ed6a64 --- /dev/null +++ b/src/elements/ia-topnav/ia-topnav.ts @@ -0,0 +1,451 @@ +import { + CSSResultGroup, + LitElement, + PropertyValues, + css, + html, + nothing, +} from 'lit'; +import { customElement, property, query, state } from 'lit/decorators.js'; + +import { buildTopNavMenus, defaultTopNavConfig } from './data/menus'; +import './ia-topnav-desktop-subnav'; +import './dropdown-menu'; +import './ia-topnav-media-slider'; +import { + IATopNavConfig, + IATopNavMenuConfig, + IATopNavSecondIdentitySlotMode, + TOPNAV_MOBILE_BREAKPOINT, +} from './models'; +import './ia-topnav-primary-nav'; +import type { PrimaryNav } from './ia-topnav-primary-nav'; +import './ia-topnav-signed-out-dropdown'; +import './ia-topnav-user-menu'; +import themeStyles from '@src/themes/theme-styles'; + +@customElement('ia-topnav') +export class IATopNav extends LitElement { + @property({ type: Boolean }) localLinks = false; + + @property({ type: String }) waybackPagesArchived = ''; + + @property({ type: String }) baseHost = 'https://archive.org'; + + @property({ type: String }) mediaBaseHost = 'https://archive.org'; + + @property({ type: Boolean }) admin = false; + + @property({ type: Boolean }) canManageFlags = false; + + @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; + + @property({ type: Boolean }) hideSearch = false; + + @property({ type: String }) itemIdentifier = ''; + + /** + * Email of the item's uploader. When set for an admin viewing an item, the + * user menu gets an "uploader:" section with user admin / user privs links. + */ + @property({ type: String }) uploader = ''; + + /** + * Biblio URL for a texts item, which must already carry a query string + * (the item identifier is appended to it as `&ignored=`). When set for an + * admin viewing an item, the user menu gets biblio / bookview / jp2 zip links. + */ + @property({ type: String }) biblio = ''; + + @property({ type: Boolean }) mediaSliderOpen = false; + + @property({ type: String }) openMenu = ''; + + @property({ type: String }) screenName: string = ''; + + @property({ type: String }) selectedMenuOption = ''; + + @property({ type: String }) username: string = ''; + + @property({ type: String }) userProfileImagePath = + '/services/img/user/profile'; + + @property({ type: String }) + secondIdentitySlotMode: IATopNavSecondIdentitySlotMode = ''; + + @property({ type: Object }) currentTab?: { + mediatype: string; + moveTo: string; + }; + + @query('ia-topnav-primary-nav') private primaryNav?: PrimaryNav; + /** Only one of ia-topnav-user-menu or ia-topnav-signed-out-dropdown is rendered at a time. */ + @query('ia-topnav-user-menu, ia-topnav-signed-out-dropdown') + private accountDropdown?: HTMLElement; + + @state() private menus: IATopNavMenuConfig = buildTopNavMenus(); + + private boundHandleKeydown = this.handleDocumentKeydown.bind(this); + + private boundHandleClick = this.handleDocumentClick.bind(this); + + private get normalizedBaseHost() { + return !this.localLinks ? this.baseHost : ''; + } + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + :host { + --white: #fff; + --grey13: #222; + --grey20: #333; + --grey40: #666; + --grey28: #474747; + --grey60: #999; + --grey66: #aaa; + --grey80: #ccc; + --greya0: #a0a0a0; + --grey6f: #6f6f6f; + --errorYellow: #ffcd27; + + --linkColor: #4b64ff; + --linkHoverColor: var(--white); + --subnavLinkColor: var(--grey66); + --primaryTextColor: var(--white); + --inverseTextColor: var(--grey20); + --lightTextColor: var(--grey60); + --activeColor: var(--white); + --activeButtonBg: var(--grey20); + --iconFill: var(--grey60); + + --mediaMenuBg: var(--grey13); + --mediaLabelDesktopColor: var(--grey60); + --activeDesktopMenuIcon: var(--grey28); + + --mediaSliderBg: var(--grey20); + --mediaSliderDesktopBg: var(--grey28); + + --primaryNavBg: var(--grey13); + --primaryNavBottomBorder: var(--grey20); + + --desktopSubnavBg: var(--grey20); + + --dropdownMenuBg: var(--grey20); + --dropdownMenuInfoItem: var(--greya0); + --dropdownMenuDivider: var(--grey40); + --inverseDropdownMenuInfoItem: var(--grey6f); + + --loginTextColor: var(--grey60); + + --themeFontFamily: 'Helvetica Neue', Helvetica, Arial, sans-serif; + --logoWidthTablet: 263px; + + --savePageSubmitBg: var(--grey13); + --savePageSubmitText: var(--white); + --savePageInputBorder: var(--grey60); + --savePageErrorText: var(--errorYellow); + + color: var(--primaryTextColor); + font-family: var(--themeFontFamily); + } + + ia-topnav-primary-nav:focus { + outline: none !important; + } + + #close-layer { + display: none; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 3; + } + #close-layer.visible { + display: block; + } + + .topnav { + position: relative; + z-index: 4; + } + + @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { + ia-topnav-desktop-subnav { + display: none; + } + } + `, + ]; + } + + updated(props: PropertyValues) { + if ( + props.has('username') || + props.has('waybackPagesArchived') || + props.has('itemIdentifier') || + props.has('uploader') || + props.has('biblio') || + props.has('localLinks') || + props.has('baseHost') + ) { + this.menuSetup(); + } + } + + connectedCallback() { + super.connectedCallback(); + document.addEventListener('keydown', this.boundHandleKeydown); + document.addEventListener('click', this.boundHandleClick); + } + + disconnectedCallback() { + super.disconnectedCallback(); + document.removeEventListener('keydown', this.boundHandleKeydown); + document.removeEventListener('click', this.boundHandleClick); + } + + private handleDocumentKeydown(e: KeyboardEvent) { + if (e.key === 'Escape') { + this.openMenu = ''; + this.mediaSliderOpen = false; + } + } + + private handleDocumentClick(e: MouseEvent) { + if (!this.openMenu) return; + const path = e.composedPath(); + if (!path.includes(this)) { + this.closeMenus(); + } + } + + menuSetup() { + // re/build the nav + this.menus = buildTopNavMenus( + this.username, + this.normalizedBaseHost, + this.waybackPagesArchived, + this.itemIdentifier, + this.uploader, + this.biblio, + ); + } + + menuToggled(e: CustomEvent) { + const currentMenu = this.openMenu; + this.openMenu = currentMenu === e.detail.menuName ? '' : e.detail.menuName; + // Keeps media slider open if media menu is open + if (this.openMenu === 'media') { + return; + } + this.closeMediaSlider(); + + if (this.openMenu === 'user' || this.openMenu === 'login') { + if (this.primaryNav && this.accountDropdown) { + const right = this.primaryNav.getAccountDropdownOffset(); + this.accountDropdown.style.setProperty( + '--dropdownMenuRight', + `${right}px`, + ); + } + } + } + + openMediaSlider() { + this.mediaSliderOpen = true; + } + + closeMediaSlider() { + this.mediaSliderOpen = false; + this.selectedMenuOption = ''; + } + + closeMenus() { + this.openMenu = ''; + this.closeMediaSlider(); + } + + trackClick(e: CustomEvent) { + this.dispatchEvent( + new CustomEvent('analyticsClick', { + bubbles: true, + composed: true, + detail: e.detail, + }), + ); + } + + trackSubmit(e: CustomEvent) { + this.dispatchEvent( + new CustomEvent('analyticsSubmit', { + bubbles: true, + composed: true, + detail: e.detail, + }), + ); + } + + mediaTypeSelected(e: CustomEvent) { + if (this.selectedMenuOption === e.detail.mediatype) { + this.closeMediaSlider(); + return; + } + this.selectedMenuOption = e.detail.mediatype; + this.openMediaSlider(); + } + + get signedOutOpened() { + return this.openMenu === 'login'; + } + + get userMenuOpened() { + return this.openMenu === 'user'; + } + + get userMenuTabIndex() { + return this.userMenuOpened ? '' : '-1'; + } + + get signedOutTabIndex() { + return this.signedOutOpened ? '' : '-1'; + } + + get closeLayerClass() { + return !!this.openMenu || this.mediaSliderOpen ? 'visible' : ''; + } + + get userMenu() { + return html` + + (this.currentTab = e.detail)} + > + `; + } + + get signedOutDropdown() { + return html` + { + this.currentTab = e.detail; + }} + > + `; + } + + get signedOutMenuItems() { + return this.menus.signedOut; + } + + /** + * Most users just get the basic menu items. + * For users with `/items` priv, additional admin menu items are included too. + * Having the `/flags` priv adds a further admin item for managing flags. + * A `biblio` URL adds a section of book-scanning links, and an `uploader` + * adds a section with the uploader's email and account admin links. Each + * section is rendered with a divider above it. + */ + get userMenuItems() { + const basicItems = this.menus.user; + if (!this.itemIdentifier || !this.admin) return [basicItems]; + + let adminItems = this.menus.userAdmin; + if (this.canManageFlags) { + adminItems = adminItems.concat(this.menus.userAdminFlags); + } + + // The built sections are empty until the matching prop is set and the + // menus have been rebuilt, so gating on them keeps a divider from ever + // rendering above an empty section. + const { userAdminBiblio, userAdminUploader } = this.menus; + const sections = [basicItems, adminItems]; + if (userAdminBiblio.length) sections.push(userAdminBiblio); + if (userAdminUploader.length) sections.push(userAdminUploader); + return sections; + } + + get allowSecondaryIcon() { + return this.secondIdentitySlotMode === 'allow'; + } + + get searchSlot() { + return html``; + } + + get secondLogoSlot() { + return this.allowSecondaryIcon + ? html` + + + ` + : nothing; + } + + get separatorTemplate() { + return html``; + } + + render() { + return html` +
    + + ${this.secondLogoSlot} ${this.searchSlot} + + + (this.currentTab = e.detail)} + > +
    + ${this.username ? this.userMenu : this.signedOutDropdown} + +
    + `; + } +} diff --git a/src/elements/ia-topnav/lib/format-url.ts b/src/elements/ia-topnav/lib/format-url.ts new file mode 100644 index 00000000..712dc356 --- /dev/null +++ b/src/elements/ia-topnav/lib/format-url.ts @@ -0,0 +1,2 @@ +export default (url: string = '', baseHost: string): string => + /^https?:/.test(url) ? url : (`${baseHost}${url}` as string & Location); diff --git a/src/elements/ia-topnav/lib/keyboard-navigation.ts b/src/elements/ia-topnav/lib/keyboard-navigation.ts new file mode 100644 index 00000000..57783279 --- /dev/null +++ b/src/elements/ia-topnav/lib/keyboard-navigation.ts @@ -0,0 +1,171 @@ +export default class KeyboardNavigation { + elementsContainer: HTMLElement; + menuOption: string; + focusableElements: HTMLElement[]; + focusedIndex: number; + + /** + * Constructor for the KeyboardNavigation class. + * @param {HTMLElement} elementsContainer - The container element that holds the focusable elements. + * @param {string} menuOption - The type of menu option ('web' or 'usermenu'). + */ + constructor(elementsContainer: HTMLElement, menuOption: string) { + this.elementsContainer = elementsContainer; + this.menuOption = menuOption; + this.focusableElements = this.getFocusableElements(); + this.focusedIndex = 0; // always start from first element + + if (menuOption !== 'search') { + this.focusableElements[this.focusedIndex]?.focus(); + } + this.handleKeyDown = this.handleKeyDown.bind(this); + } + + /** + * Gets an array of focusable elements within the container. + * @returns {HTMLElement[]} An array of focusable elements. + */ + getFocusableElements(): HTMLElement[] { + const focusableTagSelectors = 'a[href], button, input, [tabindex]'; + + const isFocusable = (el: Element) => + !el.hasAttribute('disabled') && + el.getAttribute('aria-hidden') !== 'true' && + el.getAttribute('tabindex') !== '-1'; + + let elements; + if (this.menuOption === 'web') { + // wayback focusable elements + const waybackSlider = this.elementsContainer.querySelector( + 'ia-topnav-wayback-slider', + )?.shadowRoot; + const waybackSearch = waybackSlider?.querySelector( + 'ia-topnav-wayback-search', + ); + const waybackSearchElements = Array.from( + waybackSearch?.shadowRoot?.querySelectorAll(focusableTagSelectors) ?? + [], + ); + + const normalElements = Array.from( + waybackSlider?.querySelectorAll(focusableTagSelectors) ?? [], + ); + + // wayback save-form focusable elements + const savePageForm = waybackSlider?.querySelector( + 'ia-topnav-save-page-form', + ); + const savePageFormElements = Array.from( + savePageForm?.shadowRoot?.querySelectorAll(focusableTagSelectors) ?? [], + ); + + elements = [ + ...waybackSearchElements, + ...normalElements, + ...savePageFormElements, + ]; + } else { + elements = this.elementsContainer.querySelectorAll(focusableTagSelectors); + } + + return Array.from(elements ?? []).filter(isFocusable) as HTMLElement[]; + } + + /** + * Handles keyboard events and focuses the appropriate element. + * @param {KeyboardEvent} event - The keyboard event object. + */ + handleKeyDown(event: KeyboardEvent) { + const target = event.composedPath()[0] as HTMLElement; + + // Ignore events from editable fields + if ( + target instanceof HTMLInputElement || + target instanceof HTMLTextAreaElement || + target.isContentEditable + ) { + return; + } + + const { key } = event; + const isArrowKey = [ + 'ArrowDown', + 'ArrowRight', + 'ArrowUp', + 'ArrowLeft', + ].includes(key); + const isTabKey = key === 'Tab'; + + if (isArrowKey) { + this.handleArrowKey(key); + event.preventDefault(); + } else if (isTabKey) { + this.handleTabKey(event); + } + } + + /** + * Handles arrow key events and focuses the next or previous element for topnav sub-nav and usermenu + * @param {string} key - The key that was pressed ('ArrowDown', 'ArrowRight', 'ArrowUp', or 'ArrowLeft'). + */ + handleArrowKey(key: string) { + const isDownOrRight = ['ArrowDown', 'ArrowRight'].includes(key); + if (isDownOrRight) { + this.focusNext(); + } else { + this.focusPrevious(); + } + } + + /** + * Handles the Tab key event and focuses the next or previous menu item. + * @param {KeyboardEvent} event - The keyboard event object. + */ + handleTabKey(event: KeyboardEvent) { + const isShiftPressed = event.shiftKey; + + this.emitFocusToOtherMenuItems(isShiftPressed); + + this.focusableElements[this.focusedIndex]?.blur(); + if (!['search'].includes(this.menuOption)) { + event.preventDefault(); + } + } + + /** + * Focuses the previous focusable element in the container. + */ + focusPrevious() { + if (this.focusableElements.length === 0) return; + this.focusedIndex = + (this.focusedIndex - 1 + this.focusableElements.length) % + this.focusableElements.length; + this.focusableElements[this.focusedIndex]?.focus(); + } + + /** + * Focuses the next focusable element in the container. + */ + focusNext() { + if (this.focusableElements.length === 0) return; + this.focusedIndex = (this.focusedIndex + 1) % this.focusableElements.length; + this.focusableElements[this.focusedIndex]?.focus(); + } + + /** + * Focuses the other parent menu items based on the provided flag. + * @param {boolean} isPrevious - A flag indicating whether to focus the previous menu item. + */ + emitFocusToOtherMenuItems(isPrevious: boolean = false) { + this.elementsContainer.dispatchEvent( + new CustomEvent('focusToOtherMenuItem', { + bubbles: true, + composed: true, + detail: { + mediatype: this.menuOption, + moveTo: isPrevious ? 'prev' : 'next', + }, + }), + ); + } +} diff --git a/src/elements/ia-topnav/lib/make-boolean-string.ts b/src/elements/ia-topnav/lib/make-boolean-string.ts new file mode 100644 index 00000000..fec5d93d --- /dev/null +++ b/src/elements/ia-topnav/lib/make-boolean-string.ts @@ -0,0 +1,12 @@ +export function makeBooleanFromString(value: string): 'true' | 'false' { + const lowerValue = value.toLowerCase(); + let booleanValue: boolean = false; + if (lowerValue === 'true' || lowerValue === '1') { + booleanValue = true; + } + return makeBooleanString(booleanValue); +} + +export function makeBooleanString(value: boolean): 'true' | 'false' { + return value ? 'true' : 'false'; +} diff --git a/src/elements/ia-topnav/lib/query-handler.ts b/src/elements/ia-topnav/lib/query-handler.ts new file mode 100644 index 00000000..010ecff8 --- /dev/null +++ b/src/elements/ia-topnav/lib/query-handler.ts @@ -0,0 +1,7 @@ +/* istanbul ignore file */ + +export default { + performQuery(query: string) { + window.location.href = `https://web.archive.org/web/*/${query}`; + }, +}; diff --git a/src/elements/ia-topnav/lib/t-sentence-case.ts b/src/elements/ia-topnav/lib/t-sentence-case.ts new file mode 100644 index 00000000..8939247c --- /dev/null +++ b/src/elements/ia-topnav/lib/t-sentence-case.ts @@ -0,0 +1,10 @@ +const toSentenceCase = (phrase: string): string => { + const words = phrase.split(' '); + const lastWord = words.pop(); + const capitalizedWord = `${lastWord?.substr(0, 1).toUpperCase()}${lastWord?.substr(1)}`; + return words.length + ? toSentenceCase(`${words.join(' ')}${capitalizedWord}`) + : capitalizedWord; +}; + +export default toSentenceCase; diff --git a/src/elements/ia-topnav/models.ts b/src/elements/ia-topnav/models.ts new file mode 100644 index 00000000..f4c71a65 --- /dev/null +++ b/src/elements/ia-topnav/models.ts @@ -0,0 +1,70 @@ +/** + * The pixel width at which ia-topnav switches from mobile to desktop layout. + * Desktop styles apply at `min-width: TOPNAV_MOBILE_BREAKPOINT px`. + * Mobile styles apply at `max-width: (TOPNAV_MOBILE_BREAKPOINT - 1) px`. + * + * Exported so that host applications can derive their own media queries from + * this value rather than hard-coding it independently. + */ +export const TOPNAV_MOBILE_BREAKPOINT = 890; + +export interface IATopNavConfig { + /** + * Google Analytics event category + */ + eventCategory?: string; + + /** + * Copy to display for number of pages archived at the top of the Wayback search form + * + * ie. "425 billion" + */ + waybackPagesArchived?: string; + + /** + * Map from dropdown item ids to any callout text that should be applied beside them + */ + callouts?: Record; +} + +export interface IATopNavLink { + title: string; + + url?: string; + + class?: string; + + icon?: string; + + analyticsEvent?: string; + + external?: boolean; +} + +export interface IATopNavMediaMenu { + heading: string; + iconLinks: IATopNavLink[]; + featuredLinks: IATopNavLink[]; + links: IATopNavLink[]; + mobileAppsLinks: IATopNavLink[]; + browserExtensionsLinks: IATopNavLink[]; + archiveItLinks: IATopNavLink[]; +} + +export interface IATopNavMenuConfig { + audio: IATopNavMediaMenu; + images: IATopNavMediaMenu; + more: IATopNavMediaMenu; + signedOut: IATopNavLink[]; + software: IATopNavMediaMenu; + texts: IATopNavMediaMenu; + user: IATopNavLink[]; + userAdmin: IATopNavLink[]; + userAdminFlags: IATopNavLink[]; + userAdminBiblio: IATopNavLink[]; + userAdminUploader: IATopNavLink[]; + video: IATopNavMediaMenu; + web: IATopNavMediaMenu; +} + +export type IATopNavSecondIdentitySlotMode = 'allow' | ''; diff --git a/src/elements/ia-topnav/subnav-list-styles.ts b/src/elements/ia-topnav/subnav-list-styles.ts new file mode 100644 index 00000000..966ed9e8 --- /dev/null +++ b/src/elements/ia-topnav/subnav-list-styles.ts @@ -0,0 +1,49 @@ +import { css } from 'lit'; +import { TOPNAV_MOBILE_BREAKPOINT } from './models'; + +export const subnavListCSS = css` + h4 { + font-size: 1.6rem; + } + + a { + text-decoration: none; + color: var(--activeColor); + } + + ul { + padding: 0; + margin: 0; + list-style: none; + } + + li + li { + padding-top: 1.5rem; + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + h4 { + margin: 0 0 1rem 0; + font-weight: 100; + } + + ul { + font-size: 1.3rem; + } + + li { + padding-bottom: 0.5rem; + } + + li + li { + padding-top: 0; + } + + li a { + display: block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + } +`; diff --git a/src/elements/ia-topnav/tracked-element.ts b/src/elements/ia-topnav/tracked-element.ts new file mode 100644 index 00000000..f50b6c7a --- /dev/null +++ b/src/elements/ia-topnav/tracked-element.ts @@ -0,0 +1,32 @@ +import { LitElement } from 'lit'; + +export default class TrackedElement extends LitElement { + trackClick(e: Event) { + const event = (e.currentTarget as HTMLElement)?.dataset?.eventClickTracking; + if (event === undefined) return; + this.dispatchEvent( + new CustomEvent('trackClick', { + bubbles: true, + composed: true, + detail: { + event, + }, + }), + ); + } + + trackSubmit(e: Event) { + const event = (e.currentTarget as HTMLElement)?.dataset + ?.eventSubmitTracking; + if (event === undefined) return; + this.dispatchEvent( + new CustomEvent('trackSubmit', { + bubbles: true, + composed: true, + detail: { + event, + }, + }), + ); + } +} diff --git a/src/elements/index.ts b/src/elements/index.ts index 86314f78..2876f61b 100644 --- a/src/elements/index.ts +++ b/src/elements/index.ts @@ -5,3 +5,5 @@ export * from './ia-item-navigator/ia-item-navigator'; export * from './ia-item-navigator/menus/ia-itemnav-viewable-files-panel'; export * from './ia-item-navigator/menus/ia-itemnav-sort-files-button'; export * from './ia-item-navigator/menus/ia-itemnav-share-panel'; +export * from './ia-topnav/ia-topnav'; +export * from './ia-topnav/models'; diff --git a/src/themes/sr-only-styles.ts b/src/themes/sr-only-styles.ts new file mode 100644 index 00000000..fe6d77a9 --- /dev/null +++ b/src/themes/sr-only-styles.ts @@ -0,0 +1,24 @@ +import { css } from 'lit'; + +/** + * Hides content visually while leaving it available to screen readers. Apply + * to anything carrying a `sr-only` class. + */ +export const srOnlyStyles = css` + .sr-only { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + padding: 0 !important; + border: 0 !important; + overflow: hidden !important; + white-space: nowrap !important; + clip: rect(1px, 1px, 1px, 1px) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + user-select: none !important; + } +`; + +export default srOnlyStyles; From d84acb6a8a418327d28e29447967479d061dd1c1 Mon Sep 17 00:00:00 2001 From: Jason Buckner Date: Thu, 10 Sep 2026 11:30:10 -0700 Subject: [PATCH 2/8] WEBDEV-9038: Fix vacuous topnav assertions and the base class test tag Four assertions used `to.not.be.undefined` on a querySelector result. querySelector returns null, so they passed whether or not the element was found. Switching them to `to.exist` failed two tests that had never actually run: The wayback test looked for the search inside the web subnav, but the subnav renders the slider and the search sits one level inside that. The selector never matched. The login button test clicked the toggle and expected an active class. The button owns no open state; it reports the click and the parent sets openMenu. Standalone it can never go active. It now checks both halves of that contract, the event on click and the class once openMenu is set. The dropdown-menu test also registered the base class as `dropdown-menu` at module scope, a name element-names.test.ts asserts stays free. Both only passed because vitest isolates each file in its own page, so turning isolation off would have failed one of them depending on load order. The base class is registered nowhere in the source, so the test now mounts it under a tag inside the topnav's own namespace. Also drops a comment that explained the icon fill by contrast with its old package, and moves the wayback search to the getter form of styles that every other element here uses. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JpyQxVSkZFrWxxGamCcNhY --- ...0556f2fd06be03324b4e01bbdae32cd6e6d23d.png | Bin 0 -> 2082 bytes ...6fb5239ff4806c2f0a82f33df0e13cd7011a79.png | Bin 0 -> 2973 bytes src/elements/ia-topnav/dropdown-menu.test.ts | 13 +- .../ia-topnav/ia-topnav-login-button.test.ts | 23 +- .../ia-topnav/ia-topnav-media-slider.test.ts | 14 +- .../ia-topnav/ia-topnav-wayback-search.ts | 317 +++++++++--------- 6 files changed, 194 insertions(+), 173 deletions(-) create mode 100644 .vitest-attachments/750556f2fd06be03324b4e01bbdae32cd6e6d23d.png create mode 100644 .vitest-attachments/8d6fb5239ff4806c2f0a82f33df0e13cd7011a79.png diff --git a/.vitest-attachments/750556f2fd06be03324b4e01bbdae32cd6e6d23d.png b/.vitest-attachments/750556f2fd06be03324b4e01bbdae32cd6e6d23d.png new file mode 100644 index 0000000000000000000000000000000000000000..47767d2f3db3e57c7b5cb7d5e6f5d4e0ed04e8ff GIT binary patch literal 2082 zcmeAS@N?(olHy`uVBq!ia0y~yVDx2RV7kD;1QeOwv~@BA1N(JP7srr_Id3jA@-i53 z95DEFXMgI4ja%e?m6tbcF?X2z{K9j~FO__?^PK08GDpKv_u@O4hD6# qC=0CM|NmbQa_}pV!3L`0nHgejI2P=w?qmguFnGH9xvXltbOYF3jWX&Xtvlz#uYJqsGGhV1or%SCs+sv%17CThDAUMs| zx$0bJyvz$!U2E*>rD2K+3f5Wgf@SI)Dqc1LQ9%(Z*KZ$7mZksqlOOM&lRSCe=bZDr z?o@=a?lB)lUIqZCcmOyeaXkVd^~K$l0C3`ROk~)V+=lJtP-Sv9QnXij z-Z^#5tJrm-iJypxlu*8m#rB^Jr)7L4Ir$3~`{9+}-h9jXThGW5wen$ZRG7B7gq~=D zZ~cU4vGsX@tbC@>XGN^;w&B(FnqY-FRL<4Tx2M3q@1X!&SssNU_wbDooS7z~Lc+_e zEv6}E+DQZXVm7Xo$YGjPtz?!}UqP_t&NfHEw8UQOl2vEy5?T#1ISaHBSXZCj7@^Ax zUulQoa8Y{sqOl{Dk3U>3IpKNEGAE*malBj7$0PSW;Uc&4d1EO8MJm|o?(6H5Rp3C2 zj!)MxwL>m0l%$IV9z2F|Us%pqd2lv*(70LeRNHiSUgz!|Bmiw@I-bDt27g5m-9&L^ zTsC#7_inS%Kc&Y_^t4QBv{}ulIu7dw7T^ZX*o;+v$-Z@jy!}6csfqKA1e3A_F-_PX zI|~c&+qlLPQ_F}LaQ!~oNWG=aSV6 zovi(F6sYcut$u$InzcYP09`R#j+x1}ZB!687j|GS9u2qxLt865f1?~*jV9Z6`5F%q zVGXa~MX+ft46i5M5SsQFr9b~-#SBV4AIZ0P?tBut%enbZaTg`2zMZffCa?U<;K~T z=$dn>`G)PqH6MX#>t`8{$~n+yQ{JI38oO^Vkn;Yj3T1@t7^)$;veolWwRQX@0=Pek zjxJ>!zQQ+Pf2TazO~aA7Y12xVsM8@?%11RMucG&Adv)H}I~UB`TvS5Csf&7uWXM}N zz+=j~+8}3|GY-ZS?J2xF^1(t_z)?h}0^)}KvTe#vz(kdw3njfWn|Y{RdpEY)O}Zz7 z!LRjw@#)(0HpUNUY@GO<<-t7N=Jn4zNCW+l=bcW;z)Ok}O~+7HT+RcAc6I1_ov$^) zI}_!rwpfh1VN7E%Ee&`P6sDljXi|LK?tw}Q3+Q;JVlm;KDPCMZLUK`; +const component = html``; -describe('', () => { +describe('', () => { test('sets default properties', async () => { const el = await fixture(component); expect(el.animated).to.be.false; @@ -20,6 +25,6 @@ describe('', () => { const el = await fixture(component); el.animated = true; await el.updateComplete; - expect(el.shadowRoot?.querySelector('.closed')).to.not.be.undefined; + expect(el.shadowRoot?.querySelector('.closed')).to.exist; }); }); diff --git a/src/elements/ia-topnav/ia-topnav-login-button.test.ts b/src/elements/ia-topnav/ia-topnav-login-button.test.ts index d0477be7..67e8aa82 100644 --- a/src/elements/ia-topnav/ia-topnav-login-button.test.ts +++ b/src/elements/ia-topnav/ia-topnav-login-button.test.ts @@ -1,21 +1,32 @@ -import { fixture } from '@open-wc/testing-helpers'; +import { fixture, oneEvent } from '@open-wc/testing-helpers'; import { html } from 'lit'; +import { describe, expect, test } from 'vitest'; + import './ia-topnav-login-button'; -import { LoginButton } from './ia-topnav-login-button'; +import type { LoginButton } from './ia-topnav-login-button'; -import { describe, expect, test } from 'vitest'; const component = html``; describe('', () => { - test('toggles active class when avatar clicked', async () => { + test('reports the click rather than opening itself', async () => { const el = await fixture(component); const toggle = el.shadowRoot?.querySelector( '.dropdown-toggle', ) as HTMLAnchorElement; - toggle?.click(); + setTimeout(() => toggle.click()); + const event = await oneEvent(el, 'menuToggled'); + + expect(event.detail.menuName).to.equal('login'); + expect(el.shadowRoot?.querySelector('.active')).to.not.exist; + }); + + test('marks the toggle active once the parent opens the login menu', async () => { + const el = await fixture(component); + + el.openMenu = 'login'; await el.updateComplete; - expect(el.shadowRoot?.querySelector('.active')).to.not.be.undefined; + expect(el.shadowRoot?.querySelector('.active')).to.exist; }); }); diff --git a/src/elements/ia-topnav/ia-topnav-media-slider.test.ts b/src/elements/ia-topnav/ia-topnav-media-slider.test.ts index fc3a1d8d..1650d227 100644 --- a/src/elements/ia-topnav/ia-topnav-media-slider.test.ts +++ b/src/elements/ia-topnav/ia-topnav-media-slider.test.ts @@ -1,5 +1,5 @@ import { fixture } from '@open-wc/testing-helpers'; -import { html } from 'lit'; +import { html, type LitElement } from 'lit'; import './ia-topnav-media-slider'; import { buildTopNavMenus } from './data/menus'; @@ -49,10 +49,14 @@ describe('', () => { test('renders the Wayback component when web menu selected', async () => { const mediaSlider = await fixture(component(false, 'web')); - const waybackSearch = mediaSlider.shadowRoot + const waybackSlider = mediaSlider.shadowRoot ?.querySelector('ia-topnav-media-subnav[menu=web]') - ?.shadowRoot?.querySelector('ia-topnav-wayback-search'); - expect(waybackSearch).to.not.be.undefined; + ?.shadowRoot?.querySelector('ia-topnav-wayback-slider'); + expect(waybackSlider).to.exist; + + await (waybackSlider as LitElement)?.updateComplete; + expect(waybackSlider?.shadowRoot?.querySelector('ia-topnav-wayback-search')) + .to.exist; }); test('renders the more links component when more menu selected', async () => { @@ -60,6 +64,6 @@ describe('', () => { const moreSlider = mediaSlider.shadowRoot ?.querySelector('ia-topnav-media-subnav[menu=more]') ?.shadowRoot?.querySelector('ia-topnav-more-slider'); - expect(moreSlider).to.not.be.undefined; + expect(moreSlider).to.exist; }); }); diff --git a/src/elements/ia-topnav/ia-topnav-wayback-search.ts b/src/elements/ia-topnav/ia-topnav-wayback-search.ts index a9cb7de3..8b7aa1ed 100644 --- a/src/elements/ia-topnav/ia-topnav-wayback-search.ts +++ b/src/elements/ia-topnav/ia-topnav-wayback-search.ts @@ -87,187 +87,188 @@ export class IATopNavWaybackSearch extends LitElement { this.dispatchEvent(new CustomEvent('waybackMachineLogoLink')); } - static styles: CSSResultGroup = [ - themeStyles, - srOnlyStyles, - css` - :host { - --topnav-wayback-input-text-color--: var( - --ia-theme-secondary-text-color, - #666 - ); - --topnav-wayback-input-bg--: var( - --ia-theme-secondary-background-color, - #fff - ); - /* - * The desktop icon had no fallback when this lived in its own package - * and nothing has ever set it, so the fill resolved to invalid and the - * glyph painted black against the dark nav. It follows the topnav's - * icon color now. + static get styles(): CSSResultGroup { + return [ + themeStyles, + srOnlyStyles, + css` + :host { + --topnav-wayback-input-text-color--: var( + --ia-theme-secondary-text-color, + #666 + ); + --topnav-wayback-input-bg--: var( + --ia-theme-secondary-background-color, + #fff + ); + /* + * Follows the topnav's icon color unless a host overrides it. The + * fallback matters: petabox scopes its own value to a bare + * ia-wayback-search selector, which never reaches this nested copy. */ - --topnav-wayback-desktop-icon-fill--: var( - --desktopSearchIconFill, - var(--iconFill) - ); - - font: normal 1.2rem/1.5 var(--themeFontFamily); - } - - form { - max-width: 600px; - } - - p { - margin-top: 0; - font-weight: 200; - } - - a { - font-weight: 500; - text-decoration: none; - color: var(--activeColor); - } - - fieldset { - padding: 0.7rem 2rem; - margin: 1.5rem 0; - box-sizing: border-box; - text-align: center; - border: none; - border-radius: 7px; - background-color: #fcf5e6; - box-shadow: 3px 3px 0 0 #c3ad97; - } - - fieldset a { - font-size: 0; - } - - img { - width: 100%; - max-width: 215px; - max-height: 60px; - margin-bottom: 1.3rem; - vertical-align: middle; - } - - input { - display: block; - width: 100%; - height: 3rem; - padding: 0.5rem 1rem 0.5rem 3rem; - font: normal 1.2rem/1.5 var(--themeFontFamily); - color: var(--topnav-wayback-input-text-color--); - box-sizing: border-box; - border: 1px solid var(--grey80); - border-radius: 2rem; - background: var(--topnav-wayback-input-bg--); - } - - input:focus { - border-color: #66afe9; - outline: none; - } - - .search-field { - position: relative; - overflow: hidden; - } - - .search-field svg { - position: absolute; - top: 3px; - left: 3px; - width: 2.4rem; - height: 2.4rem; - } - - .search-field .fill-color { - fill: var(--iconFill); - } - - @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + --topnav-wayback-desktop-icon-fill--: var( + --desktopSearchIconFill, + var(--iconFill) + ); + + font: normal 1.2rem/1.5 var(--themeFontFamily); + } + form { - margin: 0 auto; + max-width: 600px; } p { - margin-bottom: 3rem; - font-size: 1.6rem; - text-align: center; + margin-top: 0; + font-weight: 200; } - img { - margin: 0; + a { + font-weight: 500; + text-decoration: none; + color: var(--activeColor); } fieldset { - margin: 0 auto; + padding: 0.7rem 2rem; + margin: 1.5rem 0; + box-sizing: border-box; + text-align: center; + border: none; + border-radius: 7px; + background-color: #fcf5e6; + box-shadow: 3px 3px 0 0 #c3ad97; } - fieldset a, - .search-field { - display: inline-block; - width: 49%; + fieldset a { + font-size: 0; + } + + img { + width: 100%; + max-width: 215px; + max-height: 60px; + margin-bottom: 1.3rem; vertical-align: middle; } - fieldset a { - text-align: center; + input { + display: block; + width: 100%; + height: 3rem; + padding: 0.5rem 1rem 0.5rem 3rem; + font: normal 1.2rem/1.5 var(--themeFontFamily); + color: var(--topnav-wayback-input-text-color--); + box-sizing: border-box; + border: 1px solid var(--grey80); + border-radius: 2rem; + background: var(--topnav-wayback-input-bg--); + } + + input:focus { + border-color: #66afe9; + outline: none; + } + + .search-field { + position: relative; + overflow: hidden; } .search-field svg { - top: 2px; + position: absolute; + top: 3px; + left: 3px; + width: 2.4rem; + height: 2.4rem; } .search-field .fill-color { - fill: var(--topnav-wayback-desktop-icon-fill--); + fill: var(--iconFill); } - } - `, - css` - p { - margin-bottom: 1rem; - font-size: 1.6rem; - text-align: center; - } - - fieldset { - padding: 0.5rem; - border-radius: 5px; - box-shadow: none; - } - - input { - padding-left: 3rem; - margin-top: 0.3rem; - font-size: 1.4rem; - border-color: #bca38e; - background: #fff; - } - - input::placeholder, - input::-webkit-input-placeholder { - color: #8e8e8e; - } - - .search-field svg { - top: 50%; - transform: translateY(-50%); - } - - @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { - fieldset a, - .search-field { - display: block; - width: auto; + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + form { + margin: 0 auto; + } + + p { + margin-bottom: 3rem; + font-size: 1.6rem; + text-align: center; + } + + img { + margin: 0; + } + + fieldset { + margin: 0 auto; + } + + fieldset a, + .search-field { + display: inline-block; + width: 49%; + vertical-align: middle; + } + + fieldset a { + text-align: center; + } + + .search-field svg { + top: 2px; + } + + .search-field .fill-color { + fill: var(--topnav-wayback-desktop-icon-fill--); + } + } + `, + css` + p { + margin-bottom: 1rem; + font-size: 1.6rem; + text-align: center; } - fieldset a { - margin: 0 1.5rem; + fieldset { + padding: 0.5rem; + border-radius: 5px; + box-shadow: none; + } + + input { + padding-left: 3rem; + margin-top: 0.3rem; + font-size: 1.4rem; + border-color: #bca38e; + background: #fff; + } + + input::placeholder, + input::-webkit-input-placeholder { + color: #8e8e8e; + } + + .search-field svg { + top: 50%; + transform: translateY(-50%); } - } - `, - ]; + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + fieldset a, + .search-field { + display: block; + width: auto; + } + + fieldset a { + margin: 0 1.5rem; + } + } + `, + ]; + } } From 91aadbe7c11611d4c3aa65740cd9aed7d60d3fb3 Mon Sep 17 00:00:00 2001 From: Jason Buckner Date: Thu, 10 Sep 2026 11:31:56 -0700 Subject: [PATCH 3/8] WEBDEV-9038: Restore the desktop wayback search icon fill The topnav's :host declares every other color knob, but this one had gone missing, so the nested wayback search read an undefined variable and the desktop glyph painted black. The package README still documents it as var(--grey20), which is what it goes back to. The search keeps a fallback to the topnav's general icon color for the case where it is mounted on its own. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JpyQxVSkZFrWxxGamCcNhY --- src/elements/ia-topnav/ia-topnav-wayback-search.ts | 6 +++--- src/elements/ia-topnav/ia-topnav.ts | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/elements/ia-topnav/ia-topnav-wayback-search.ts b/src/elements/ia-topnav/ia-topnav-wayback-search.ts index 8b7aa1ed..43236288 100644 --- a/src/elements/ia-topnav/ia-topnav-wayback-search.ts +++ b/src/elements/ia-topnav/ia-topnav-wayback-search.ts @@ -102,9 +102,9 @@ export class IATopNavWaybackSearch extends LitElement { #fff ); /* - * Follows the topnav's icon color unless a host overrides it. The - * fallback matters: petabox scopes its own value to a bare - * ia-wayback-search selector, which never reaches this nested copy. + * The topnav declares this alongside its other color knobs, so the + * desktop glyph is darker than the mobile one. The fallback covers + * mounting this search outside a topnav. */ --topnav-wayback-desktop-icon-fill--: var( --desktopSearchIconFill, diff --git a/src/elements/ia-topnav/ia-topnav.ts b/src/elements/ia-topnav/ia-topnav.ts index 58ed6a64..93b302aa 100644 --- a/src/elements/ia-topnav/ia-topnav.ts +++ b/src/elements/ia-topnav/ia-topnav.ts @@ -119,6 +119,7 @@ export class IATopNav extends LitElement { --activeColor: var(--white); --activeButtonBg: var(--grey20); --iconFill: var(--grey60); + --desktopSearchIconFill: var(--grey20); --mediaMenuBg: var(--grey13); --mediaLabelDesktopColor: var(--grey60); From 8e23502d8baff60c4aa32602180b7d18198a85da Mon Sep 17 00:00:00 2001 From: Jason Buckner Date: Thu, 10 Sep 2026 11:34:41 -0700 Subject: [PATCH 4/8] WEBDEV-9038: Use a literal fallback for the desktop wayback icon fill The fallback only fires when the search is mounted outside a topnav, and in that case none of the topnav's greys are declared either, so a var() fallback is as unresolved as the value it was covering for. fill inherits, so that paints black rather than falling through. A literal is the only fallback that actually does anything there. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01JpyQxVSkZFrWxxGamCcNhY --- ...9a5fa1346607d46e811e177765ac099b7189eda8.png | Bin 0 -> 74022 bytes .../ia-topnav/ia-topnav-wayback-search.ts | 12 +++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 .vitest-attachments/9a5fa1346607d46e811e177765ac099b7189eda8.png diff --git a/.vitest-attachments/9a5fa1346607d46e811e177765ac099b7189eda8.png b/.vitest-attachments/9a5fa1346607d46e811e177765ac099b7189eda8.png new file mode 100644 index 0000000000000000000000000000000000000000..66cc096a49bd37287277ed9d269661743dcfbde2 GIT binary patch literal 74022 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 Date: Mon, 14 Sep 2026 16:05:17 -0700 Subject: [PATCH 5/8] WEBDEV-9038: Untrack the vitest attachment PNGs Vitest writes these under .vitest-attachments when a test attaches an image, so they are run output, not source. main already ignores the directory, but .gitignore only applies to untracked files and these had already been committed here, so the rule never caught them. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01DaEr5YT1xpjK5ydNZPvjwx --- ...750556f2fd06be03324b4e01bbdae32cd6e6d23d.png | Bin 2082 -> 0 bytes ...82b84ccced5d0f90dee41023cd32a38de3fa308d.png | Bin 78063 -> 0 bytes ...8d6fb5239ff4806c2f0a82f33df0e13cd7011a79.png | Bin 2973 -> 0 bytes ...9a5fa1346607d46e811e177765ac099b7189eda8.png | Bin 74022 -> 0 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .vitest-attachments/750556f2fd06be03324b4e01bbdae32cd6e6d23d.png delete mode 100644 .vitest-attachments/82b84ccced5d0f90dee41023cd32a38de3fa308d.png delete mode 100644 .vitest-attachments/8d6fb5239ff4806c2f0a82f33df0e13cd7011a79.png delete mode 100644 .vitest-attachments/9a5fa1346607d46e811e177765ac099b7189eda8.png diff --git a/.vitest-attachments/750556f2fd06be03324b4e01bbdae32cd6e6d23d.png b/.vitest-attachments/750556f2fd06be03324b4e01bbdae32cd6e6d23d.png deleted file mode 100644 index 47767d2f3db3e57c7b5cb7d5e6f5d4e0ed04e8ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2082 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�@A5N5^u<3$fJ!4 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

    A)JwtD$QR!a?#B>u<@ZBe432 zog49i6g;n}r<6e#Bn3|y`l5aDt$c~@S@t#S`8)Xzl-~$;m zoAQky>ibbI#^MMcAs)QH=5|~HQ-^4anz!{0f<#>@NjY}@YRa0ylY~FogEox}Z zOZT?!>+|uzk`*ZtI!lo{AeQGSrV+`1F9hmudsTHuNI}lfsI79d=;FM7xIjunR zG_;w#RGyFS8_>C)P~40?n{Ai}k)rl6Ux(5Wt7?jXm3UN=(!4okmx6ziIDP^xJUZN) zauDVWEa5ITgc2_Z>VxA(L`wf!wO((E*IATFd`uym8@jstf>$LF5b{#E#<$p5dvMd! zk0Lf+=;+>-B>T&mMdea${$@9v429*h9l0)-1s6%-YDp>m`Vla`uD;KP3GJKhbG0CT zuK|zCgw3zjUuBn3_Q;D=47jC+%l#ZUG$%Q0|1WWxQLZF<>w!)Eub6L^DzwYF<8+8y zgPVByo$mRSB)x)I^+3aA6CwV24cq=(l@m{AjmNnBc?%2KvKQAzZmA{k8*j_zcWln^ zJREus&197lhw>nQ;OH=~u)}R#`yc3Z@rvGG^1rsSsTKW*qxZOAxls3)yy zh3uPV80FG6F$+%AnlyID~e6%IJxPR($yz;Qk@s6gORimU}jOh zgx)%yRzaH?rVg1rCd$anhQK_%KI-mDLT3NDF8sTx*=_!>Hj!8lpe-Z!4dMeB+)%||WcRA0DUHOK|XL(8rS_MIH@A#~$FnXo|A!VrS>PZL= zgEEjf8?>QRzW`5*NcLc?(XvevNnQ6EvED;=0`rbEW|23nSeo=rZqOH_NqwQq18FI| zB(`MfPXp}@GxUkSswG(8>_0vLmBaCHbe6(8U44={Ey2${ng3#x37}h46&z= zNiZS&3Ov)Vc0g}fyUzip<&H~#gEzG;EXofbH1>oK3xEIv@s(V~l&2`v__bh^kA4WSs$_tc|O8sZ~Hu*POaK2l{)3-^Tq5{B`Ll4H=WzM*(_94M*L>Ql5>}{j14BGuU&@fKv#Ug zkCgk;y%~jb^tbYUFZo)`s5=2fQkm3CK>c8t;T1~I@vx|#2at4k$`%oW>%%g=jD3nL zZUeKkV?QJFJ|Rev^kJenSg=o8VT`;mu|<-(xV;#&Nz{S7Ya_ea?bYw%K2Yr$E6DEU zOLL(rqgB$raK^xS5ay2`hHf9#VrKd~PD#aJGGJ`n#1^@*mb<1s2y&4B#pwX^j<0Ob z`yzGVhGMYzy5I<3m#rO;581>#!BIwtKE-$(FU<8nSpX^@z)PzSyg&ZA-}Dx@I$r&! zVdPf<<410jwHW8fXeRTW0{1XI7R>4%uwX=t0^&;`3Bf0YM+P|^_uOFi6if$5i<)#B zv5#z55{Wgi7Z7lb%&K^uaxdodz7urKN3nB4mn6ePAtT&d%}p}Wm-259h7`Az5v*SIFr8m$DcGbUKEZ$Z zI<72E?p>ev$I|Zd{?6xS?vFcd)uj7|vzZSaePH_0Lx5xj#g}XD4vxe`|4*#EZZc(z z7{_kk(&taw#oG!IXvtw%vzi(AArr4~VcjSwtAvyDt1n-jZQtum_f=pgGixZ&fWvh| z!l!XmgTM-lC)YB+8>?!F9#n|XOqK*Nb)c6#E_4~CF2)y;%$n*V7wx^9%E}$K1n{H9 zD_g`PobCWUyG=?oWyrf`b}|Y|CrvgDG>BXbg23E`D^hFGx{W=O-^g9zML`&KoGKuB zc5uoMqZHT{uJrxgb(4a5%Ajjvu>3}^?Mk;7n5%jNrDb&tV#gV57KJ%g<%Et^=y20P z%TD$<3V097Ng}Ky#_pKymv)UIzr|$hsL+v-USA|rooH;!V#Geyv6q)y`{PlZ&PL6g z?uK09i{``po?XoKTRy*D6X zWD`&_&md(XWp`0e@?=uyz%`}wUJtP`g+J$xj6g4;`0BW{R8Pvgdb#gbt7WlZoq9C> zSK$e440JY%xea|wQhlUVsk8js zV*{Sbbh6X-8)yQHNk_;?xheyj15xxk0ue#H=HB% zp(m|yn=3<%)UWi7eyB(<^6Q)cuThof`NG48_!|I9I45fJf;#cx!w4`+LF?gj{`Y@W zOH69iH<*Fhg0iCuan4k^!pln3*ulzbQI$k}KXy=vYFrs}WoXA&4xKp*xNH@Vvo{Mk zAr>3$dV=}Yi0{NNMt%UmN#9ku)Zx;&ohS%VB?t)yW6=uOeC9!6_C!-sF5kY71ZuOy zu`veiOzou!%+zyh2NR(~pr?kGi2E_1f%kH@;si!nuG}+GFozRIi*DhYv&03kr}BAV zrw9@MsbZgjLHk4Vi*Avf$l3PAe!w@a_*vu&{ww$*z>iGy5q4)RKYon4Md`fZjh&&Iy> z&D!8q8?WVG)4zYi+B%5A<0@M>Zw3fHT$)B|KP$R@6|U-w8vt2Tiau)AEQSc(tKpcts*oPV4o5t!n{4GMU z7&&;dXW0^5>f;8CniTpln}Jd{TR6QZR7uU`Mlv9nBb=Bqr|oJpn*M~-zTn6QI8A{Z4Y{wAj*@P0K^S`kg zfspyG4A?K~Lx5Gh5W_#0xCW72LvGU&uu1rG%1)|g6e`6ZGm!!fKuva_I~`DR2{!7x z2Z~oGY0G<(pOJ$o%zTVvs%+dLxp&m5=`a?(q`~WW0fy+IhTIF zifh2!&wFh$Mi?80bSC$9^&a=Bu4w~nF<2StMX*&;2oN*y3o`Tx3BSiCmgtHqRD4QF zpE3%ZL6Tr-<`$XHoSTlBD_x8y-_En_A0|ek{VIs&JGiUj{pV;n?X(NT1)8%4j=WQG z7^HH+3)vtv%b}b1MOy~n0fyD!LyQwiNg1w*JGX~-`GnyKq?$Gd&TYQGe@x~^_5DGO~V-u9@zDWAai=44v z&vvAYGT>&0AnDx(fVuR9U?#4=$eF#8xtLfVDD>-1Wxr2T2G0mJ+%g7@#HH{r$Yjva z{7xu#30J{VJ4Yg339zUgf;vu^oF#vr{R;S$wgq&y=l7)sl69H#waV*EKwnWU%ccX@ z_cdM&>z;3QZWzJ&EExHCuNC2%ioX2sH$IMM!e~e_@>SnKCMiO+$P%?M^2r=Z^9wm( zrGH#x_ra&w=(3RdU#6YTvv!!uz!|!;Qr_WM)`gmEl#75f z7V??Eu|aAH?+y*!SDki)to;H66CPE5B1hZhGb0`(U^&ZF)+ z=cOfMQ-6jzUhNv0x&I{cWfz-js#97H-hw0m9#`Qtb0G-^$&)$*WV&FL3#X31J2vR% ztJ-@Oc8slR|9Jdi5a=%h^kH0mOKLvtXJqk9QYA)!K5*ksI|tn+kCFYppESEJ7`qJy zI?|S_XNQGiB zE{8)i2~nBDM@G_id@(|7Z#9<|4fqo3D>RaopE3KS;0%dbh<(?W9|%^M$cvX&T}?ST zoC&qolcEQp$j@>GsB~9eqH~9&^zC0%ic#h~Va*wZn;8W`k?Mg(6!Btl=+EL_ofp zQpcohHE1Sy+Ey(VUjbKTo-oacq}ZM*p{<$74&zZ_a(*Vb@rGN3oZ$SG3hBS>ah3l# z7q`r9cRUMi6%eBNTU+H{hRP_XXohX_ThFuX%|fUFeorkx^rltIP{1Edco~||;_Dn) zz9^jL6O0V}Q^?5bSlN(LBTxns1%8h@x*w^0*P4)F#j0C=;DpNMmSD)S+tu1xKKtWB z;)t*3o9`k`5WwOo2CYCHhmsaC4hCGZP@kL3ME=3fQgd|Yd{OI%089t!+1E1-9oH89ta@0HE97SoCHvLt0@(H`iBQE zmUqnE9~uzCF$*(2XOdcyL5ub!tUzF=Z6l#fQ>1j7GvW?HFyKYf_C8wd+@O{ zLO6O17^xy`K8Bv144!ARgUzQnZnffUO~i66bOxnpff%hEwmn|n&5fU8liu6)rR_AT ztozM#YOlC!Ia;hch>kK@Vo|UdA!?~wuKEuLlNYarkqxg-K3Yr46GIX>`J&lJ!kFHd z)TCC^98J+n2u*2w{NK^Ri*MsHi8%3pMaoWn&>>HH>vmKl+VDx3K%YQxD_8f~nlcaD zm~8GB!}9tziukfsTpJl(hl;Y7wmHV!)sN?~7jAzhvduCZ%LMlv^T6MaMS7u2`nXZv?}4g)&}n-$8!MJ{F*WU8V12_lD)C z7Wr~HG!vx+{P*M?9!w%b?OI=csp9UT!-jhDQo+Mqc2Pe zY5j6G$b;PEpFu$^5+c5k#Cr;lOWE zr|X00ra62EU3QHOD;|wRIsG+j-NA&=H0gfbFBz+naHsSM3p}dZ&z~D~bYIiF3Zo8w z2zb>FVdx^w7^a)wTp%O9cIdioY;>nQ%RIld-t5IDhx;vZ%+Kk_R!&OH2yKhlm&SNHK8 zZ>PHo`8=`NY$L}+K2l8{E{&?*2Qc90+mKDjP z*i>9+5*2=2ZxqMViA~ZeWe7VV$~++p>o?%vJIO@rVI0>C(=5Q?Vst6AFGg#C}kx5`L$ZXf>$J>3S|*I&AVX> zq{25cyQ6b6i^b-)dzDu-frDKBQ|Hu=T_o?>ZbbwCIDAmw({78tc~fvag;N#JKtRB` zt;u)gXTV(&`YXnzWaQc+Sn)D+xpjD0_~=r{5w}r_yZ@}aV#Xb6o4}&DosK`8JvvN8LO51;sIY#kOC7x6JFYvLUjp|V4+)Rzf_pU_eBM zMiS67H@@JRd{6eM11q%si$0g9hhh@(+py}N9n6n<3*@p!TMDZMPLh9kf0fIYi87lC zXHjIvBQyKGA)e}-zp%B(|m`+PT#b zRYuDhN)4B`F&eFC>GegsY*R&+$+wXoR|_zDcfR9iw$qSo8UTiQD2KmQN8M(80KSwd zE?W5LaJc|0`pRwAb23kUf&BgEvyYsFMwl1f=dbg|bG?3FCMz=H9#GyYL&#)Dg+d1L?ldqd~))l%-$pT?;jT>S~AeME3!M0*;!f^hH85SNb&B{KYtKHA^&GQA`yX4ntLXo9N`lUQX z_+Qb84W?(Ix;DDn!dssj!sS3++-CSpuutlAvur&~aYe3eaN@bWXm zu_a=K>`k|q%jW94MVkL{(APZS|JPHsYZbCibN+S`i)sj?aeQRM!DA*tv^hGL^w2Zw z=Sgf-%XSnXL)V~_o_wqm?Zx|iN%-x&71bu2JUMx4xf)TvdHQ|?l(Cvk8%O-_79#e8 zYVLCdEY9(#0l?iZ>wiuzaUNd*-CUAli_iEvov_2(@PnI0$1l!Si_7A=6`HURw=u^u z3F}jq*`h?Y$~Yb(5h!k{n>By1P|Xv2Ym~ry^k(^{V-e8PeBxY>;4O%b-w@mEZB0Kz z<{vAw-`T8q29GK$^<144Ihq_zlb`i-=$n~1yLwkqXb<*u1Js08>Dq|zImNjC$M3W! zvFd-BTXS`rCx^*Uc)x{)#gVr-R9Cx}1uTWY)48!W3i+(!2lJd0Ebi)?^0;5U#_~LJ zPQf7U?+UCYCjtLPFXFOEE|KkIhs8QSTcal&&mlSx8Kac*d&$#Xt90nzUoaAw;&dm~QrKBVI7M9dpIj56D&f#nFau#%K-}o2=)fh6Ys4rZJYT&!n!b4Kgko z<$h$sF(>Un-4P_rF{cu9((h+u)rhWxOeq<{eBmOP^pjt2HZswxFi+hdi+Tw2My8(z zT>H)$H$~$`zbRA-ohDQN)Mi9#hofR=Y5#Y%B@@^uj@?pkUccZO^Pg!6tOZaJC|Hv{ zt^PXEhS^nxTYwtyLrSsKnbu zvlULo0?PL>l82p@droIO03l+V)xL+~9E*~YcuoeXMPaL=7_Ff4?8$clIb6!P_U$zw62P;?W4m!z4 z#dLJ_jxzNfs~c`L`M-9sj%sxU4%#ZYK!Iv$IXa1E13m0j1=8fr7^1es(5EuP&d`0J?j2#S#${41rc;p0B5JelY(}6hKq>^gQ zZ4oQ$D=#Gr52pi{n<9EN1*`O*f2~#aG+>eeiqssB-gb@Q_l^ahC9ss9pj&v!Y6t4i z?mV1dAEa%?fLI7AhlWmltY%7`NStI1xxoQZ6t{ggmYuYzhejtcIkR5&NTQ?g%vaf9 zKFQF}C%R4EQpDZJ!EgO6ibm}((Y?Mhe5~*uulMiOyI00}yv+%RGz98{57otpxAqa$ z%xo(6lC!nO-+y3!NQPrn6($0m66Ps-xeWD?Ek#a}6~$>YfzlBiV;MQ6BN2imjo-$g zXc*4}pw{xktoRB7>ch*wnS=Fqbu3viI^17S-@mTqlXUV883g{@{po#s=#ZkK*51K7 zX>z6Wf}NcYp`|}WpvAUY+{w&d;5y|(vPFNnb14svmWqU%Ol>0I>F2|r1Q2NG%zH@>haH5Su;GyYMI<=qicj$n z<)R7L=8?Kv4JD13T9AUP_EcyVCJHTm3E+C{7|W%h_yMYPdi0Pn#DU`LTHsCG{n`3& zRZM!Zk+MNdtX5zpW8Jaqw|0{g`Mfw55%$=XaV4Pvwc*+Tv8tFDuW7qn3kq@v=9Xz5 zt4?*JkKJ0p8!*MFFhgWT8Fe0reiF$?#*L`TXL`f6GA{}tNQ9z%&-$Q$tU#Gap#8sw zg1j<1Z4G9W1crrD0D*fEDl48VlCcY@wP4C3&)d`VjY5s2P&IheHU0>DN&> z7G<`q%U7+|jk|QfOOq8dvd6u)TXIUj41xKC_+P$L0=|NxDsmKzmL@~A6i2z~Sx^L4 zDxr~8?KSGyKN$Sq%P2gs9go>2@{e6>0Tm20;)uT?k!l0qw@HjLBIz0W(;f=zo|FIr z=d|Ew06$pYva+u0Nmh0*ohba2g@-R3KO8r6^dGzx55CVKxIpxt~7j)^K!eCm9k?Y5#&eK#DMSmM*(Iq~l zA45$^8ItzVHVgUe6CaBo)lVfp^ygU`Km-uap_^(2x9EVppW&2h(kGZ$N+T1MH0yNL z77bEB-E1uk&bEOi-R~#Q%^eYDA&a>*iDk8RrjWBl*mU6K)2E>X%YV%bwDErK!$&bv z49nRV-jlNTUnvsAM8-zgv69nlED;6c4pH9QJtsffh>IwtvB-VWB!wXdMN$|_xS)fvV7y1O=91Fbt z@hp3z9`mOQPs3+RdP*X*#66jH9(PI_oY&We9@ja-(is!r4*;m0Z#7h+2=&cph~ukD z)a(y&d>RGYo1D)+1&=kWoGD+CmC5+*mz5x*^5Rv>XvvV7BM@RA$rw19rx}D*2ta?= z!iA{9B8q8h916|Z{o#)F(+D7EVSOS__nia+Oo(h3(kK+J((*0YCpy-MHIjf!-0A6F z7*F$Vkz&-X^@|5RSK$8Y@#im~?Gg;@^2X0aGyxOjocGBZzo_>7=?hoP6U2TF%V|1u zj~CJMo5^EFf1I`@{9+EL>GJ@_C2SN%?izh3O%cjJ3Qw8>Z-Hj-F#C2*N%;a?{rII- zu3$Xz(eRiZ?fbSK3S;JgEnh~%KkX14<1|UdmXab@P9@tlWcdPee#5XBFfucc2B+KN zBPDeMLk}x@46Go`{OD+a{}JM2;vJq4?F}sMhe0B&N+@X2z)9tp=iDJl_{7q^SCPii z;yU{87I5#+jH4B+0VpFORf9`S+cxkg>XOy@=k#0)vNf7~5XQlmrdP zvKLvvX?)fY6YB;@mPJE1{X4sR&7HroEe2m^x?=ORT~2NSimHG+)*9xFxm`aRHATcd7~Q0(A;PKdxE8a(`B|(t|9;ivw)EC|%jQMzk+F>f$Pt~% zbOR^bDB@TQl&zL~V*JFgc1FVdhNO(`M-lJaLzk|` zNm~KOR^4S62!HAtCXi3`_yjOT2bhrZ4eqoLq=SmM3q^g-H+hP288{8_vdldX0>N^0 z84jqEwULcydVcv)s7z*YX%7IyXiB0b%6!KSL~bsbnIDGR4#dBiR6B(x5)ICRMLm^a z41L{_V45Y~(seg_yRVC@RI}YH1ZLwtwI{JAR852gNf*X1uf@K7KouN4lE^4PC1=uN zXTx@R%N@J(&j%0br!gMl!JX|)n>^zrkf(u(_tVdJgD2@}M-JdwfET($(SLCsvqbpD zLjwq6K~E-769_?tvXd{?x8X|m3QaNzs~7N(ja`j3agCk1z~{CWye_*@>qD5KUlsSc zbD@{TB4`0nOdvoXfW)orW6*LyZK4qFKtou-3E1DXPtbAh!Ruzg(aj1%3kWQS$;%?THj^qJ%`=YA#TP?UMICs-I2Y&i=+D?^6tc zbGdfF(X2yTniKzgO*Gt*3L|w{>=V;stJWqYUtiY2B67XF)BaPLXlU*qKN1#{k#rLe zG-@~Xn$*g78+2oYs$+OsPoX4UcI1@hIpIa=ScG6Fhz@x=$Ysv&xQXq?O`#{VmUO9h zNmbDrv~NPGPw&4t;Uj&x`r7QS)8ohfk3owl+MYW=sw-KB-flh*sKLa0-97RZD$Vs! z#*$XsYZxkoQuyRLF9*JcQC2gK5v}`+Q)j^bHw%!1C}3UK_^>vluZ~4Z&{xq({|Jm6 z+IgKEewYY31vmj5lRb=GU!{OlG{p+}=pj`3 z*CXUDvJNXlFc~q;_ClWj`M^ND=!y+OuIH79i2B6iB7<08bz|{71TO_`-p;kMmcq~k zJRIMv>8~MKLDP%N7&!1x4qGc&qNC>Uy|v2@FX^}a+!)nb2*AQl9{4;u$&m8Ff$ywS zApCh|){_mFZKNA;H{_<`V};ML&ffqQ!%2%ImkyfvYV$tN#--s5HixGwf5DhpGD3c0 zjDSvj%3rMq`ROT*nbe{YyGtgUEzi5CS~7M$iYZ|?YMPiD?m2I%`l^{MD6Nlqz-Lo@ z_MFs=WBtp;Ja-sh2TPs`cURd;4IO0G_+?0v{6q$s>#tB)3Nfu=r=rS$EJmuGdW-E$-MXRVh5YwMnR6tMDC1%{A=e*4fb^bhtv5lC=4k;&s`j;2v*e*mi+$9;T` zi!MPdZdp#$Fpa6nP2=r&H%F+9B*M(o(0@I$N9ak-tJV6J6dvEW3up*FR(t=lgD;P< zD_71B@KzQYeOQI8sf=-1%&J`06&sdF8|!kB0sYL>_v&tQyG_3VOtMv3y(2(xa-6b4 zS$f|h1sb<4dS5cP{MdqT7S)(S%cK*Xv-QbI{kuZc$Cdj}by$F5u0%MbBInN#;9Pw z2z89tU&SY222QK$_F&rmy_ED%2k9jIT|TmMDSTXS&1cSf3B0+-T>8%9&^wFkM{N;l z&I4y-gfHVkV35Bzk#U{D^V-gbXjy1F#HNm$*tOs7TL1%xeAmCHE;RyLc$!Oc1D=sc zLn7@EMb-9hpq3g**JN54WhYhJ4xVa1P;A>rHn8b-EJxLUhQ%JFh8kw`BO~p5v;Z?} zMSANuR5sF{_b?pOJ1Av*2=73z*fZx&WEfFt8dhl;_q`AL4dA``V2+hRtwUZ9Di)R) z&zg#BY+ol4tGxI4IvYW_CGl+`DNCh6V?lnGNnx@1Fij(LTfa8M?Eq4$BofI;o+ zeqmmeFoCy-hpPvK^MfMx{E2`}(}WUPj*S7#w(+UOMfw)iP!Az2!d|MA#Rny}T}ZSj zVSAN1e)e9)YFD8_7Ls^Qg#=^R{*5Ysblqi7KC8P#m}O2RmuEXexTwjMNKjbesaz0? z^nlBK7D9S~2nCtw)2iP@Tka4O>xlM^beFVSA<=Va39F z<%bNOZDnuBP&iiyZ?LpG;43|P>!qHoNjrQjYtUnd;P=Io>3iv7FoYG&&w}P=EcIz$ zC$nt-CtFNbW!KZOpAgrMVn11sxmBn%=ANZ4+J6m$&qz1PI+isFg|)KrCZjc_xqJ)v z=Uwjl0X+=eG}I3k`p4=ob8^Q<27aYbxbC^XQ$x&T85)Vv_Or$>@Mx|mkyLJMf(7;@ zW1NAI#XicXCf->74p2T8+-IUF)hZGq?LdTaLi;qTn9v)m+B1#XWF49K+XNoQ9B-o_ zsY{04xnIqybEAHuhBPZc@h|glK90A+gb};8lU{!V(NFG7TAK5Cl*spqC}N^^2V~yt zszjrA%rkow^7fQwj(^M72z?jtu5C`_KW)p_Q&Tf!wvUg%j04{`o6%ts5$Oe$26E}F z5VH6*#P*2pysOF?y~P8LN#sM?K=d?2AA-keF^(mZe&sr3K$eO%G4in>z+*6#BP-u@ zH-lGJNheo;3XKieprlRG);#`s&d_qv^-8b0Fjv{BEb-f=wc?XO(M(a8;S7TV z4F8}6q!-jM*4HQky|1c@wPT7YK00ggt7*a4rQDaR@Ku6J+rq*I{#*nI;!n=(6bs>8 zl`VTNj?kKCkMoA_^%PSnn36E&TPsruW+Qdei}$MrCwz(VTwAU(DM@B^tZpR?CZNG< zkmFP674JV^>}v+V`B_b`qyXA=pV?k~);npSQ^D@iwvl5oG{2f}A?xUb^QEb@IKVL_ zCvoa99Ly!OmX3Yb^BnLdf=a&($q7y2Gg2Z%^H2o}8d7gApvjn)&%V%6Do1QZ)%XFG zZ&!y`?qSRt@0Hd<#x!3gyxE&6V{H4`N~4HsJ#D*x);Ns?+66kLwpiH|ZRa9oDD6y8 zC`e>crisIGR9xyeC)_dgByiW~Ebc!&%ZVugL2Qzg5oUF}2jP)rCx}%6ccxTW8 z5OEse^(zl_oL8mAT0G%@nJa}JwrWee%uSnny3eXjb}xtPE+$u7-baFt26B?B##D9| zY@4WN_>SVGO{z6be?RbG)9v1b^^SN6_z2=vDil*xB=8ybQY=X?V zq3pW>3$qaiL7%c`1Xpv_RaY*R(8In6Moi^;b)C4J$z59lKbr8OlF;ZRwSKSXugyNZ zyX4W8Jl2}OZh~fdMW_AKP#}51!>N|tjydRA8=LfbY_bj}DAXQ(ijEfXfa|Op+n5Z1 zMCePtxmiEK-2Oo;q=}2!a%?k3P{Ic5kqjv)AbgGg;Qipm8rh0EJ%M+Yp#lY%VRMya ziR;SiKU8Tr0k(C2De<58fMx?BkZk=JuAhC3x|3t6 z75fQxj)LxH6_J9^n$ik1YqEM2u?$_+djs;hzRYh4fpHrwt&4MlF`xO5_ZU&NNAOh# z(8IHs8=)0%z4(D)g84Ay-V?d5 zQS@vBwOTil6FO!g3`IBq6ccL)WK!O9ID(hR;vH9*kY1{Cs|@KOjgP1@2}K*bEy6;! zDHqNFLp)7jhy31*hf-QmpC{y?#lJ?lzck-C!;!doG^7rv=*OTcl5$;V(5-FQ2ndI2DxFIl-8VC0r22s&U-TB_5 zhVb1*5guDCL&POf3pXo~D}B<&)9lx@Q1i9?X9})-Q(JH+r^MyB+z6vme~^z-`9%(D)-Enuh+%>T5W{r#UsvjPk9sjOATzK)4(KWTr!UBh4a8;uFuBTcE9xHRFV~8 zW~GTB)?Zw)qo++;?V@)4|9ECgV(4D@V71$qrZD}AaaQ^$10jelcR;@ZZZ$B$*j@Jz zq0Iq63w}{ePMKtOi5@>V{Pui^m&ORTbXb?IOk;u2b2uenz`z*z#ErH;<5_YU(PfT> z-cm3#HT|iAjM)c@tg#5L5)B@R(EjuVa_2kOC=>&9}$+Yv=&%3e-;bKPl_-VcOzz6t7=x+s-_C!dY z$a?3a5+|AHNUknjHt5_75kWQ1Kz5olO1xyU+K`Di;1LSHpw~2WNTPI%@RV&r5b`v0 zxgMgPSWCFi(*hyLQ-d)}C7V4@OJ-G>u!!7*NU%H9z7uycOtOssEBeydk-AeVI{W$6 zN?VFn@4BQ0c|A~3dG3efq8Tctk9DnpB{*YdRpg3a+;hi3Jl)>2e4*+PCM0~_YtbX5 z{sRkq4w_6n3U!JNs9pu|)`o84eoJD9K?v%7NHuMMPA*}b&)mC?M?A1*;()di1@jwr z-^k|%bd9?pRu*^|ebht*e8tu#1E5=*gm#FeJWtH9Sk0zi591pn>-Gl|TY)&0vg=6K zw?%MClY##|j#)_v0|fj_rDUDpx`l0%jRh(no@y=`LIa~I&l$_QY3cv2ei`3K?xv&_ ztX^aUBN=;#`2`Io8>};|@g&yTGPbzjpLh{%6Z45tVNA=uk06XRLALAlPl#&+_ ze>rh=n1{`P9J%PRREs?aJ!T+4YOS#^g-z}CBQ3&3n^&C#yQ%4m3=&t|Q6tNnDRoT- zwdG=7)|fBEnvPSR>qTz-b9YF7GltO zNI0*_xGgbzoy*vS_9ns|Y%I}FSok9p21+fAgsPpz`aEII5lA6D>+)BRf@cn906v6M zxSL|Owj$)<7>Uuv+RV+caYFAXs5LU~{leT^I<14h%k*2ZXRF|$NvIDc#Zkpo-%BCUG@5jaus1aAhrIAsWN7xQviuOfByHy z%TS!-fe0<9pB<^AvN1j*ywkb2^h87x+A?vR-l%#DVe`t9Qxuy6XEp&fiIQ3L|JB5c zeg}Q9ajyD0WYx)PlYm|n)*~iO&9h`hk|2z*0{$>LWIe=7+soSzAejR31*L%{$JzK| zD&VW~nRL~2nl^W?hY3|nJH`s8(<;cz3!x=}^wFh)`N(L?U!G4);-T>X=7Tsg#pOP_ z)kUL%%Hx(SP)e2Xa|*Z#GSjqGsF-{y!(C^5i~#X^UqdJQPSO4qSf)8XnI1<-L~dyM zxrm<*asCiM%#Iy+2rwJQX^&JO*DL;Y;`|YK(EK_z=1lh-)4&6JnoT}luG88GTLNQ+ zEV}O#2lNfHRByL?mtarz!37CS5Iu=fA29@}jRSKklhi=bu@s(>3F=@A_k_xoFy43m zXaNAOl<`XFwJ}S!v4<&`WVXTy_%bL@*@`X;)<8Y*1T6hzc18gGii(Y!;hA9f!zRVJ zMI;bmjZ;vtynKY5`k>4MQ|pmr9BY36Rr;Ra|5tFe53f=2fDfQKE7)hbbUx(wZe zwDY74=rRx&-T>zT0R((r3#{g8M+d!ER-~9RI%=?VM?ql|fOcJ3UZnY=3FD&wdZO4@ zLVamI^4;K7?#rb~LgvaF4Q%_exIfx^4+gS>X8 z`5HKE{7DSPvpBsMKTKcK6&fGN@?+(aQcY}&^nzD#GC%O%_Cl}+&D11oVNEhCdjM{I z$=&rdml{B^UNzKZ@p@>MWlaKE5K?AGw6msT&He|_?d}_XgTmtiZ8mhH|M^7bc1X$j zA4*FPX2TvaIWEI0MZPY|GoU8lcZW*vNlxe|t5pG@Ev$;8^c&;!W{#?q_dHkpFH}Fi z84S=Cv8_DcD;XFpy%-V>-rYtVje!nsjGEG4rTZ%%my4oexr4!j&xXtzTOF)T@3N99 z^ZU=*c^7?P(*MHz^LeLBUB4khrO0Soe09>8RhKWhcsN*dd4C2%P{F1! zdLZO@YoB6|%~7pJj*mr-OFL=3`Hp>#U^Nki-}>Rtl_AAj@87RGLSJbhl#2DDlN1zx z>sMHg8Sk^rI*aPn&8GM{VBg&tBy4k(#d>W~YS>!W^%lqR^&mA7He}4YLNj9r0q^wR z>$~A22Tp*Y9kszZKiY?0p_cb4Z#TVVmmQ|UiMG`H5wJDD-QlSqmSb(bat2XMv|(JX zH?>YZ+ff`)K1q4tyC}T5(AO?UZ_tyeqFnM?4fx4vMFdC%fHa;6rJ}peHm=fRn0dHP zOj-nXUtt%;54eIeTpM?Wtl<_6su0O`i3(qeB(m8!J`7XhZi2?&No8uq&qvP3BnT7w z=t76vsU~Rc#LSZKdp_8Aec$|$i0Ji^surM7o`11Ax9)1>!_9qSEOQ;uqPq4+KOeB@?Wwy$jZ z*#oOqkJd2TTIlz6zUXF$KV7vPN>*jlsfX}nzs`0kyqiA>CZ?a)Bo7~#u(WNG_QT;P zKA~j+r}0`7@6gv25GK!lM=kM%jxP?FNt76V)9U$g&&Tk3opt)!yzZ! zml>HdJ>unH1)U<&1x{}MFQYm6P2#bqZC8IBrKN_6UM0X>*|vtfuCJ(-aUdQ_oP&_F zRl4bjEGv@VnePdtj2Hat|0}AO`i|^JVMpVlAMPEG{`h@3 zpD0Oppj`i{By4UA%se%nq8=qQU_*TSF12jLfyxY~U}dm_%$4BaTpL7#-Ia!oMO*_1 z&|dfxppClP>39^EH;Pbwq3DoaZVnVv!WncbotTL<}%%{d)&wRj{7%|$ApZ2kwSTP>m^6()bNSnJV5{|%S z7&QuOJVB^Wt-2!Qj@GiDkRWD378=o*A~=n|;5hBfGG7@2ZO4|Jgbw9pvlyy>+!_h= z!6z*~wrHWe!L7nb6KYa}o5*$5z50nK_aRKJO6Vyi)sj{3>1HaEYebn`v@8GmsMf11ksG-ZqS3VJ0d41#*9WBTHd~PUmNxP+6}kMNw=mex%9N zIjc0FA zRdu5i7}#hC;-FWq^OkHP3>?JJ#@Z)EYjw@x>kq!6jD9StfuD<`hXb*clVr0k`gIK) zg;QjT2-55#i`H5ifoginvwydJtPcq-N9Crfs5+mPg{N#{rEs}2z@zjr1Z^rFa@qC1-fvV4bIUP-W4;xDplZZ32a3xH( z1=kL8b>hSphifM=T^~woG`qT@tJC43*EvZ8M60kcb$5bfQ5>hvXR(PCxR|+0V3Xh{ ztvDiHWT7AORvX26by~nQs2D^Kh;k}s82gS<)M6XC(vU{7J!LY~xX4e2^~^QDloTbY zj-X;k3!lFslyS!~HX9=E=~tmnuBdt@qAPuVbgX-xlr2nnGFNg5jJQS-#%h-ZyOlmf4d_%y) z`2I)CxoirwkJc^j?!Ep{G5+%RT(kkyhl#O?r>9yvPqm&H=y=d2GkQd$f zmAg?PuXE~NNj*Fv+f_%{R@L-1BOmvwlO*-cqFKZrbHm7`?tB!k{hu}GCfUCw9qVsv zagX*GTJFu?y36|iKqaJ(MML{m&alY_butlIYa%|BXJJeZ!INN$Va> ztzKK*pl-|~gB>_D*hE=}3k<8PgTrT02Rg_HcxS+GJtQrFp0K;J#R{R`DeZHYg9w$^e%}4`8?x`4P&B2phXnVEV z-TwczHwNd}A~; znZaE3ecDN?ktn|J1xpXA#?f?fvn>rFZg7V_P_O~k_rxU7_carQ(%495zLwYdi#uyf zz2n36Idf+$zUS9uL>iIDomma%RJ7Cx%$8bKuS{UqJL|U|6+G#_zXKRl>&yVMQmm@VFNlT zJ0GcFg-R^j@8g}jD9G?d0Wre-OO)gI1l#6c{}$+aU=KGZKm)#J&_@qGRpP((+I@EX zH6^Dy6h``^qm*dNnvQxWebkxoRC-_2he+IXB?(u>YZuJcYG%C|kOI+TIJznL@^03P zcySv(DFY)usaD9_lOH??C{ZPsn#_xMAG_lfZ0P6Pq3e+3$?5&_+VA?$Ma~(;8-+r_ z9k3nCS%|(V1^YuxnjE*mcea&TCgUlUnKMejnV1A-9`s3&zTX`l;~S346lA1BLNTi@ zl*8_3Y6$>fLd90Q*lh*ta`~cH(H6_|qJ7;BM9-^*WjL0>?W)zHXt?|j%5H$dTcp0^ za%VBDzhR=)f+i@??b@^>(pL>C_<>{vzb8Wb10h66iPlBl^{~3n^Iobxr_^m?;NxsM zf&qOqo?b?cS@krgac>7J_)$~f-%Fta&kOT2KBa-bc{sGoOO^i{TGurYS$G6B3j0al ziAw~NK?@vG?2x07UdEo`Kf12#!r?Xv=Yeng%T%+42IBlW5et?XM#DWn>+V)aKgmsE zSya746Wsk5(KB8=wHJfa5Ut1(CU@qWE!?;Ioc_BTjy>ogdD8CKdw05|!&%;2eIAXx|mr{JoKfqmoqh=kGUUBQbN!>Xz>zEQ&mw zw&sh)nM&Du&Mn6N!k-G!98g~p9^h~#H^cA0WqD_!N2P2Oz5xO6bWY)q!{7fm3;3yN zDa3!w<#vF=UW(qKu1*jq}311ho!m2 z=$eb{U}?X)$`Ge7b+CL8N3JCN`;^^+a4J?X-^_Qm(8H_8fO|@xhK()11A`KgF|IB8 zMi}||7mt6p>H}ORKtT7Y!C)dnV>lm}`!mbJQ4~D1zdZa^5d`Of+8XwcNPj%oqO!LL3;JTn>yv(Fe{YjXFxc~9arLhVM>B85oubOlG)X>=%Uj-= zwKsV>E5~cB;Eh<^xPz}KAM!Ta9#pP>kJ%*I7&=YU<_cdQ^JdI5_lF`dfr<&xKP$YyM& zZ%F&Mi4Zmv{_N>%EKp~+p#U944&q!TioxrZxUhNbaPbhEkB5t$GJHB1gn#O1-x}C` zwaT-%Nim)YG_s`2Ur%~$0e~cPG|~7|(YHYBI+^m>ez8l%Qd0!M}Bp`Qeq|W(dFx^?ugV?P+B5&fiNhCMj3?@9jnl&_4U* zTM35ILY&Eg#{IEUL{%=(nvq?U?V?-X3^W6GNxf52j}cPAdiVD3wQgl$#0C1@AHAB) zzbrt7I@}8F3^c`wVSrmzS5-N9j8zjoOmR{p*rZo2nh@K;Rra9#i~fOhlWEKC&9~lRD4*?l6|q5f%chJQ zx${`rDwhHGBCEhN@FI1(&%^cw=jrd-87MZTx==fiwq#QBY?d+L$<%~)XcXsR+OdO) zW5%j~mYTj|B3JeGh+KNElrM97+;Z|Z+g0)tv?mhVSSB41yi=Mb8SZ*po8{}f%J-2l zFO7P?IxhJYj-(cNBK1owHBy)1RW;xHXME|O27!lv#{qlHwG~r6u*`ZaiROkfUdCxq zdP{LIf((k)0}G%Njl+yMWteHr+L_XVy7nv{QWol0{Rby0>TGvD;&5P#Mu?~;qg*|4 zkR(hh(`1Iznl+YODp8AJ*qZtoNrax6k@jEQq86w+NKnGC63OID_VCvIJy=bp4P`Zc z7nK^iNNkWq(R{I26&-r&>23x5i4PC)g{`gv4Ds@Cm{}KQy_N7l%4b3xs-)YdzxM|c zkMyqAGL#C(@O!5+E$Uq?GYbstRscacP3qRtY1wOLo^0a*$_N(%zeI#GNBHlM#&~jw z4*rmXhE0(tD1%?KywaYtmj6^~sGT4bjZdDNK#3#JPhep$1T2b_QO`dqY)W4kT*_TFnkaXi;*VD_%xF`<^=4Ho4$VH@%OEQ zf3;*O*QWxlheG452ffNjxc{-wpJ}md-{mN0hCg+>&_DTO65Gz;Qslg~qmXO`!50{W zzbagM02~rrvI(4}`&`e3vY}Ou9BRO>R$a$1^VEZ;#dUc@%o4`BtIA8`e$EcvC}Z|_ zw*txMO`~t3ri-5$toPO>xCR5C+kMina z)_-4Vn3KmH)Pau1B1W}J6hpaSq}dNg{Jh?$dF@XV0Xv0hR%DQU z4olvMnKsM1gHYpj+hQ?U3Qn9#@>6iUG2v89)qD2Tr^aFUFG~JDkRs#dMksYpDK_@L zNryvc-LN83`=LVhyB3D8d3*q@&ZnT*Azg%{Kq(sXU%D)hhEgu}Q|PIb{eSzC>S9Fe z`oWE8t`+)nHW+ z_<@xof9W7U`3mS;Z!^YhvmeN$ClRKAe4M?XUm?qX#t&XP261E~Qr}mrp?~Ck>$8>i znox|n-)~}TbFQ<__SbL)<7yCp0-e+_(8M0FvF8MM8xn5PaV_elD5;z@dpktRRwBtp zlL~Fr&8c{PT9c*`sX*fIgW>AF`*xvrK#%qok5ieQ3pon0vGIpNR5|$qy0ubb)gyA7 z0MePM5mUYZ%7v;dpJhWasG{4RUBDzLVy7neG_Cn4izH zShh-ZBPl=m0ef>WDM8Cj{yjniOZn5)!R%N$Pr?UE=C08G&=I)=h29QHK1qv0l<&K` zQ0OaXH2*y8#N+3f^ibts^YykQd<*QtyNHrA(1mmzr{ko&KLvFC_KMPDmA&X-4!40& z_QEGeDB0J1Q9J~d?|~Mj`UZc#Ds!$lx))>MRCJkb|7_P6s_uV``QkR1>Sc%n4dcKu zlH}$UyrSyzQv8(8G*>{NC-Nz{yZiC%?|8J3*n8)QhHlP9&p>ll({EO|VA*gE zI4Xz{S_hYx>|}2d)FVC^+~I8Lr0!nWs0T1BIgzs5YM*7zdO50#(gsjBe|M&IC@HH-&w@#oJ* zwO|*(Uo1fjtI)Cenc9$pBF@90JB0>f3FaZj2u-QjZlI+;XGvp|D8NLIn_`b&RyYid z0B&fA3D9F{eG62wA=F9b_-HAFFaDeYVX^~2$HrzlulR9wc(Idtco1c2WR-m5Uo%#3 ziL7sYTt>F#%OjSuOZv;wIBqKddi+k&NRs2`fGzJKd-e40*^uW9V&mVlrj>xLw=-S< zY4Akw{7$KN!>oG?Gnh$bfe7G3>pbND*<_1g)=-aRuhzZ|pb{07k5%Z#%^<=hD36Im zL=rHD*-VlyfQgkc?77rPbvFV)WDlW@&%a}nurh-?jR;xbkh!|sPidqFt?N zpYrlJO1j7e!udpFaYw=po65PZQ3pZ~{{|m#99DW3P^ar4hJWpI+lty6F_6OMbx(JL z_Zw-o)$duR0QLQfB!qLPt=?N$Lb;W4s48P86FmN`-(#!3)$rp1bKrx0)9j0yD3X_C z>&r&#mmn+SF|S+vJG%UxY2%epOTQLx)PG42bumtUpOi^7&HcZzf}@NqSqKKvdWPFC z`qg2Ar0`tO7VrDJmx6^v_NqqR5Q~vn7ub)4lcuWZNh5FPT5wApe~V8ct`TJ;z21-6 zIf7XafV;+O*m)|(8VUdx+j3X>&OROek|tdB!^&+8UAnDwuooj-rV@1s&D^?%W`_2b z>#-+=>5`a*{n<{Ml{#x6R6SH2lX}ukk7Av#!;ozq0CSeE$Tpq(Q)*@HZK1N zJB@lL%{Y652~7oUbDqCDLHV&YcQR_0B`|&d8oZWh{Z(hn3_MvZiF#0|F>=%B(3oV| zB!t9O)K9roBTL*TI@>DI>G)KtPD#_z9~ge#0VMRedNP*5$hImoVR#L|#c(Y;IjL9& zHEA=%S=TtggM`98a@;al9{*S}tmTOjL}BPGJHF#^fY5unAMb3~Q-1fItf~tBy>T;k zsH0w;4Etm5=0!gCgluc$u>zJ>aJYoJ^uMAWG2AruANZCsLFOvB82Uel1sd4x(vP zW((!Ru#ioV-T^?-`DIZZ-M3)*23&xEvXF?;e>P6{A@syN7({_Z_$7R^pPe_Q@&Ef! zll#t{DWxOCpZXhJfK7Z3AetxsqU zw{I-E-nyx&woA zxoN#=sn#F5V-DXnhm)J~g=z^vF0~b)@y(E&RE~b}ViSY!oedfL}MS zzV<5T1MXBjSsBuUZykXG?z`$*a&zpBde(N&@BYRFq2q)wi45Iz-c7lVut&@mC(Tq@ zfw@xD79pREMt*j?CXP%%!?4>~n5C^_>9pF2hJ$)ystl=Bv#+9ti0sB2S2G1~4-ik%K6`w7@qGcbaey}m3-gWfoR}{KlaA&!ZgtOBPRk5e&-axFWx43J z+B5)pV@|7omixo+!I}!APxSe&iH}KJWhlw+~4p-b2iL!0kDV(trv|b(`xKN0_3edW^^Xc`S;F^B| zWxt~?QFYfN&v#TnQ6397TFp@CZ2T35E>t_#P)f1+uf36B-s*4qHm9AYvR{LoK90v~ z&nZ;)r@;#)qt6F)>MqGM9tyP29rNqnB8I8>&BDNvOCB}r(rW@Gu#MyqHbdFW@RM#b z84dM=FMZG}WJ@)XagOmL%it5a?^?z2f@q}4|5jfivfC5@KjYxVMLv9KNVS(j8Sf2oLMzEd0=@jL{qS^uBtgn1OKmMi4fwY`Hm&YozGxV%w^^r#~E+j2O zQ9J4L@vn@-!pWfU=o5z6pxu9;IT`VpgF$S+A7Cv6J%&g2Cn3#%O};q#KE;XcAkz+c zA38ShSog&+_FdpK_3N|Rb!>li{z-^Xyru_;2EC%JM%SLtV}B~)mTA$ek5UfMh9DzQ z+AW9}UXJ`Ir3AP`6nX;pX&mVo%wo!T3IJpzWtv7J}hD)Q4&>ugQZ3EDjUQa0*Vhjt)7h9OPl{6M7EsZtdrGp#_qtPuDm=E zXslI>+}dIxo$OyBc z7e83BkLEl+&0(_TnATgw6h)=xDb|WeV-(uww1MMyg=z*N*T+)Zwzn%F-#zHYF@$9-$VJ7)z!(NNznZ zL}3XdW|~qM=8*j50?5(X3(}QI)Ff*3?wvH&iqx( zz%^1`9Be_qW0xVSA(~AQy0f(FcVg?UY8Fk>8zjql9O-)GD;)KF74fi6J%94@{PB&4 zj(TAbn&|t9x9fRP?lJS!>QN>>LP6( zzFFmR9Cae-!YHe%a?Y1<;5U7i7S~*`^!p_;@r&EF(0Ju4)ojwAa-YBC$Ml)~qeBgv zQ8$%tW-Y>4o=t>Dpe}X08W%RT zeFLFa0{H<3)5;6a5s$&7`mc2X@ zeEUPFf&7?o(Bakdxsn-!bF*g7Rkb}Cx1R(lbW0@Gss66F7Z4INQJ;7 zi@a1~0-11`e+O}nqPc3oUjAYgFy=^EzDibbcRI*>S=7n8rmm_v72wU$6`rs&9vyS- zBJ1=;JfZv`JG^8k$20!&roCg)WfC&YP@w?DLu!%$;L2XR zS@@6A%TDwa2IMh$1cUD>T|E=wAoo}4uKFJCt%bixX^i5+k zq%YfBa8BMQS^qTyzfy_&GINy@4w#^Y``YY(n$$myx~5!cd}i{G#I25IbAvC+tdC<< zJHhF!vBX(>Put9`XG`|l!_^{kFs*^$1QzBI=MJL3nF5w788=X9Cxw=FadZT`^J;)O z_vF%jQRf27rObMCg~TrrGDC`xhe^5|7P+i-ZbVrDciYzx8#Q_;22t)B_=5fP2SiE-x{XK>)B>v3;gqtCk^dS*H7A!>GH;m(Q_Qw?Rjfo1Xd^} zH~lL+{`!(wt8qo*Aa4XO(na}=_oC_%kjJ{g{&O^PhTX|B4?m^Y;KYxK(#;$H;9Qo- zUKRc{4Mqh)xemYQrPD$X>MfDjj6C!x?Icp09*djmQ>OxP%*c)TC*VX zGNS*grQCHfao z-5nvui|{xdo%Oy}^=8R==dZY%F}ubBvM!l*67xme~Kwb zxoO-b7-zvUz2tELwg=f!IAv9{GN154uQ%KZw~4`4ZkR_k8jB0p22+il!Succwgx0w zo<@IP<8K3p2`8Kj4o9yZ5M|D_`_{rZm8HNW?w!ar=sZT#6n^HGXSWsBx$(&LC zkT&xIYy1s5ip4ODdVcE#NSK@on>96vL0Od5_hLkpX1zP+XtW-?=rsn&1nHsUhulQehL0&R70`-SF_~3 zM$>$*xU>OnRZeX7N=y(VjE~sTwof4>#--ktPVW1XYwW~?I~S?4)%-^%vF}3j;uMB# z(iEH(cs8h4SIcg1TL%fG>cpL=^F6l>6v94^W32)u>?qDq{R5kvCwMlg4D){qN0g|i z+B1;`Qu6-<&;`2Ro?rZDY{bI)fBHJhuqNZS57QwiL%M79Xr#MGD4{TrX2g^h1O%i7 zB&0;TOFAT_Bu5B{qEgbWPFh6Z{mjgUK~)N5iMnbwCS(ghplB1d}V0?`b}$at3Gh##@Z`l%Y+d6QM?JYQ1a*+~i-Lt^Z{ z(cATRa&r&W*is!#?3`<_0I}kgu0G%1qnhuO3_+~8E)(i?<-wPs4yy`Ba`Rt7Z*lzT z;vOM=W%((=Db?wX(Z4n!R>}#?Ww#p%M1_+AHkyB;PBP8y(?>)c%}Zyo>W9gNE(#0XJUAqH#u3#18A-@-GDDO9W&!_=4z`c ze#29H?O@qEXFJ>-^r|*-BcYGK1vnSC?u4ISuG01B+)zB4x?R!^ut%A05)}q)_TPvz ze)$7yUPiv`DahC}4;$cAoYB3}!1KI$5~?TC^(J+QJH&Z>2tat`fZ1rYlhY}kE%18- z%a$)Np3zUQ$W?b9j6O5O_PEyj$V9%Y<-qPH!7vWG+*<{-Y<~)rMA>p5HNmN3WxG9w zTwKA3ebX!lf6fDn{y3-2IYbSWi}_CkLM5yYrc@M!ebci#MqXRcfG_8X_kSBGb(>&MA3W;XQ0 zj?U5C>+^?(@agrHKE_bK2KE3KNQ>qS%N}7BCz1d^-*FQnLOt1Vt-RI^;{m;nJkfssboQJ*>@zZCTp`YC`_a~$blWTc&9S8;a}c=PjWad z?efV+E66ur3!)NP6+7Yr$7R(!h5gx{Wb0roSrlH z%(wxKOuFRx;D~Rpz>Q3by5$ZDP6V9F%D7vZN&ip*T#m?JBnA>3M87!>baZV<*~Elg zog)v{M_4e!>U>R^$QvBZ+>Sj=qs@OCf-r&wdJhsxOc%#T>{XQoK3~YI6)9CEFR8qF zh*oT9hxJ};ES;@i{UK1vnH+n}3fa5#n!OS6RjI1}*c_{BJN2uiwZ$emgP3|f z9M}n?9yj9!@Nv*pQ&-=Seq<9c z+2QTxzbM4|$#K=UlRf<}-RG_wV!}LMP{1=NwTgRm7!(cJ{^RX&@WkS0L>y8+Bq`*| z%4i0Q6c-b$=C?E@tmUkG5`LjN-C3_x|7#kDw1hH^qHP`Ff~WvZq)0EShMxyXrM8$9 zt@NT!gS4N05mna2+_35_EDFuVMFdNuZ>;rF+G zzwH~|Yi~RDhnP|gORS=c*xhASNWP1+?M-`?Z7bk^e8PZ4qz z?C|=8l>O*lWW}8zOcyfE{{bTJ9&`drKwkuoKYdt@`4qw~lRdrdY%`llIsh06Z@Igf z(;Bcg!hAMa?FQHW&@SGv#{DRZTkD5b0~p2I;C!J+)uRAB>fz1<&MagN<}CqW`4d_b ziXkwt37fE_oIY_yjc$rfGJ}_dH4kc^ za7+)>%;=-ILTS{$*XZN*a)u$Y2vbDji-f44nh0`FxR*hLi&}KzOHwr!3ya9+P7sGO z2;Pd6^zywG_}-bcSTrE@`z5&AeigZz^JqfMj;{GTrem+R01R?Aut=iSPdEoWpW8w6 zwv_;tk~6DE@`#~*qWP;o;`zLu&V~a=XV?Me!NC=07>{mPoxuBXQXYfG z(FHV8lBqPl#QgKr*ZU;&qC@SHWZfk?457?AS{J{Em2clr_@$C+%l|fAk^;FtW97WM zEIwZytN)#RfDwLj@s<%sDBsrM4zNj)(OpLO;Yuf5B@nglixs~r|;AyH3JR^!B>Xn zITyn}{pyD4&7{eaO}%Y-sT2*8nLKbS9y^>?g|csLfHo}$Gtl*j5qcIr7#T^~oCX^o z4~>rG*A%!0Q*&xF5pDtH1t_=-&y$8b_P0oKJP=B@0H|pLAtwns3nr!*!7fATm>Vi> z@-IEvZr-;t$txdra@wp4UzV7mtWO})9FHUzZOp2-Y+&S@AVP4|a*wqOgCYN>v(8V@ zL(*GhJ@#u$SMYIP#f4B5dom{N*YYMCJ&zP5o3%wHH+VqlXR4N{I7l8C94{QIIAuXu zmMBcc_w{#?Kc>qKU5sOr2uosVeqtl*R~f+PND`G#0c=Div%PYbw`oh;o!{IpT|cl# z8FMiz8MbeMCT9S9?D6>AvMWR6y|Qfh$Ru_^u<~?82@v06L8IGvBVJ-cR5>-_@s)eT z6J4G3Mk-y01#!CP6EEa{${b2GD1NiKvpjl(UbLV%Bg;5P>)m@fli`tI6M`=`Azck= z{A@+SDJi9=(EInPfufDSh#CxUb0D@xWEq$u@#yGuGddwDf)5g&Y zI&pbVdU4Gn?7rgtILc3dy@i}!lw>AOG4;&YMKcC92)s>9eI6#6WZujs#p?YE1P+d| zclkc0U~V@iFlwfNZ07{56O`oDzxe1ko-^4ShMx*(T2Ru#G=3BPWTl$80Zsn75bSPM zk!@iQw#nX4p}c^|DkOV4*F5}y`Q4=NIM+=zDv9}^9?dI~m=UpH);-C2HmQI!oe#kFxIXFM z=K4Fu5p#rb1RfD)9i$?w1U zsGq-W2qjcF=d?S|tHwwD!$e6_4+ulSep}yL7RyaZl*03Q4%<0Vj?OoaxOi%Y!->N7 zXbc|{cx_rSU0ADR_AxK3bMWm7o(=VDUhKy8jNQ6`rZ}DV^XTSp*eZ*f$JRln-w2h! z@U$wgPj`Z`g#1(O8qQJ?Ebivjse|UhH<;ZuOZ#RYjzWd)Za2*$g(UOOlga#kO&d_7 z>D5Ze%cq~se%-0!ZFIAgt~Fppt%^I(L|pEg^@uy_Ao`%V!3E)JFQPCDUqmLC4s{MM zPM0uW|FKJ+4A~?Rh7g*wZ$31(oEenxR=CQlxyRQjmZ9lBw46lHkf+tb`^hQ2%K~5g zE9i_leKR=m{P=MCnS&t>8{H@B>BfqJfv7AMCWZRB8|d~ab_g&)R(w?WnSZ69jtb*% z96&_t>Fk=VX5K4(c@x72DB7iiQ5sS;M!hxtizb@+jkZ)h!2h*)3e)@83=4*H&sVzn zw3}+2uZZo3yI5K3(k@#YOjsxjPLAk#hYWu^q_%Zi5uW&LYr@=c{|(pJcjZ=xI3-T9 z=CZ}MS0W!AFb~t8FIrM=;ES!CBfYFmEsqAHWU_s=4e|q+F{Tw%I+U(|rZ^<-Q`ysf zZ#84-$@o{Wc7bb2;+$@ZaF3iBr9IOl&Xt7F|8y#b@rWmXQY>@S z;^M3%5#Kh`y?Imb5jR}_)|^2;kJfl;Jp-Wl`E-yX`(_jSq1j_*GxPfQDLjA>-EDa&xZ72-!+d&Xnl zsM3LHsG^dIu0AZ#O7EGUFQDSDlS+S7Rcg>Q%bw?-8blobTBWSU=!CVo$P5l+Q=AYH zV00IFbC+Fbg{ss=I`TG|&yv|tnyL=jg_b=Ua-&ox0A!Z69hCvfDGyXgVEFAW%(?zh9HTjQmiYF|cI(oi{$4Ayk@=l0+b4k)FfC+cFzUmHyF2%s-H`LN7 z3d2hljiG<0=Q9>Dgp~Gb#W%g_K_%^V;1LU#9bJbzlZBjTR@QU4H2} zGJ}70OU7*~apY`TYXnctIN6Kq+GvkVVxDf6Z8&0$Z1ffbJ1gO?_A%#eqDDo5(+`7< zQ(gCrS}l!6npzhPmegIS^wN*FCuk2|i_OkotHBAC@wz2@n*?_Zc1MV0b^W4k0=woo zjJW<}Ds$Z*%T(?2(iZ4E-%6uWIK2NeppY5S?U#JA$#j7~q zHi+|3kbv?0&C5~Bw}yI2_Ca)rVhGQ0Y+k9`{s&Zqv7yCPSBqbn5bRIj($Wt@)$}7a z_jYTuIsV|@ggZ=r$^Y{S>6L46$21fiB8z1rn$XU}AF>}vf6-UDV(X+uo zT|LWOV{3>cxP+lYhzVhe(B><|ciM)oBj*SXg( zU}RK>Yq%@;fE_a6lbM~@Dk2>Qucl_`dfY3h=DHQfjc^KoR&~-M-SX$d>l|?}9pmk1avZlgcnMKZ2u%q+u(hR%%$ zt}`ea_VHeEJyZ2-mR_RmQ_!}b*Uzb*CNEF`x#X*tYXRmDg0+`v5a@!QJJdg(!`@~Sv z2v?-S@Fh(}Tcb%|!4`CV{FTvdJ1!{-qS3h+R=u34*sE5q+El`@cEz_NMcpw9(g3Wj z&M{85F0UE0rra=A1Ar!}1SxNBUy{^*9rjhMXoIwMQR~8t$IIN?IRi-@5%XIqKXdS+ol@pkZv)H%BEI z32zGO^TVLh9*5av_hMwuDn`(c(?;_wlg8Mj4#hi^JYehJ%2N@Ju1-=uTdxrXM^@Z9$}&v&=Tybh8)xIjq`!sR9SDCdzfgn?!L=!4`lo;d%P5$%c65EH|5|AiF2#yq(tAX9YZm`qJNt_2eQu!_kN}eUzWOZRwoH$=Z)B#qZm(9L zD;Aw_?nECJ94F8IME(u7QqfdNi6^YfUCSQe*`D+`9W471ahOEbvr3VGbs>V`H1-60cts2gR2YrwJQpdsh%U;&jMm$ z%pdy5wM(ZRAo!ZA3jXh(sOl)0W!$7+EqC{5QucZlJJY5p>2hm0;V({KcTumF z0E}4z(}p}No7F*I#iyCRLB*4=4yjJ|0KFicE-c)TaO;bu1eREAq8$BF^9&NpDc;lF z(3T|LU?Cqji7~vA-7WxYsUm;9^S}i);~?u zvxWJ2X=oT8(|i;+&6na50GIA9koz`??Pv3Uw6}pkue=TF-IEj6WYio6e&CQC__SX> z)X&dT5IWTzPodKW1we69U$;F{8_t+5^zTEzzzhQ)Z7G{(spqp z?`;ChQ6p8gTt|amX|Kyxe3%Zytw;(mFH%t#p*&Gmk7v1G z(}CbiP+~7v7#3N`#o61l^%w9dDvNl5bt7*(VtVzpL+l=5$=~ffwK2&W1IeN%p^^^e zPc>fPB1fty*&ox$oj{8$VqPC&qxb(C)&Dnn|Bu=71G+r!7gRyxq((R)o#m7yvuK&daB0E7i|vzak8ae12b6n{oh@G`{F7`7k&&eS zggKds8T7KcT~E_zz*m=Lv zFbxFtGzpEq3S?Qx?QE&{(AyT2%o0?08>AlMe!P8kdD@fxVam~d2-d}kGNrl7avnsU zoGR-$Ws51sZqN2+A+;`6<3!x=7NB9y?M(xJwyUD=qUEmE*sfgKXE8}i>Ef{k7Roj) zroUb_9UEMJ^qbYmx;J=!Sd-h?g}#Huk+%niBv*Iz5|12^^}GtInmj_bm>+14RruX~ z_y%LFtXtOg*6?8A{E#O~TK+r7m=5SL)2Bx%e)4 zF2EGuL3}CbkegDGN}HCU+2sMCmLg zv)8=tR1da(doq?}>(Ul#IFNsN#QQOXb)FB5zsNnutOTiAnVZ?3e^tlv>ITsX&n61r zEW_XagK*9hoN2Jjwng5)^_p&9dcmvOM5ifF^IWWqf$~Ft=*u12ItO!_1a;%(S|pM; zDke}ZtH$ux4a&2&j=F<3drw}_$dqU5CUHZ^!AnM+) zr!a%++kt^^tUKmCc?6lARg0X*Bji2H+SbQpot7qYiuX^(M6_rRe#zKv{`QPUa1%8t!J4xUX zSQNY9iKHufNxEa03ZEV(GUYkWt|@v#0Qb&IlHb>l$s<=5F~IW@lJQv0`sCZ_`RVXC z7x)l35;cs2;}LTj#l^+T6?Og1`~0r@fLW-dNA{i|;Vx7h0TU-8z zauFF^8s~hp(%c9LO7X$1|2&4RfzfY+t}>x%Ju;~KEf&?ki_UKQPhl>A8-TCw*=Z!I4K08nN=wO4{)B?pV(O7H>1BvN~8krDsPSaeY zLR%jpoC(9@MoC^DPWk!?YKNZbw?lD+C~C6 z=?JAZbMg_A-AR>0TIdBL{_$DzkaYWJ1o%|!q%+p7dKc*v>t#P85Rd<1NaRcGMMTj-)hsn*?Z>4CJWmQ-+#puVK}|X<1-Bux)heVv=b#Wt>$OcxpOmi zKD{=1f7J>ok;s7%bq)BVZ&W=jL~`{b2-*3+7QFP%!|17FG8K zYD>Eb=?%3cJmhV~V!g}G7y9C)oQnj!kU|Nybabpx?g|zqzeOAQC%IuuW+&S~NHTewssToegjsiCI)ZENx7*10&Fa zHG-WSCgb%hg!IMvsWb;MOLkQc8(3xbs*x1|E@S(AU>Ywt1X2hY@5#?AC?{DZZ063c&IDY{3m#JdAmUhqt^E#lEv(bc=g&O0%W@e7^ORP{B~8(cMzBX2NH0pxf(48B-*ew$ zy5~EIi+Ii{bPW0JZZJu~%)v}q-}oW09*ZK0SL%R)GWP`6E4h9a{JZa4IF!*;^*T5( zE8l$%ua=QO4!4##nlf5{K6anRWyH%rx?I<)LtwghBP|1Db)F553A+i9LFB#0wRksO z@TM>gwBQ8j!pE*;=}|z-+^aaC83nCvTfK&HW_z;DafqS4@A_fq6mqlILJ+T7(Gqb& zy3Z+A);nX0HzZDkc=|Un%nE8l?a{ffMa;0mI&V9F{=Mmr_B$Dk$Jp9rJ}EKIe0W4X z4Pfu2kxFBEQNCYd20Ef-8v23;V#%zeyzFP^tPB$H1~1Z3GY=Lom2q%zuCClPr2N1S eMA++kd>oltbOYF3jWX&Xtvlz#uYJqsGGhV1or%SCs+sv%17CThDAUMs| zx$0bJyvz$!U2E*>rD2K+3f5Wgf@SI)Dqc1LQ9%(Z*KZ$7mZksqlOOM&lRSCe=bZDr z?o@=a?lB)lUIqZCcmOyeaXkVd^~K$l0C3`ROk~)V+=lJtP-Sv9QnXij z-Z^#5tJrm-iJypxlu*8m#rB^Jr)7L4Ir$3~`{9+}-h9jXThGW5wen$ZRG7B7gq~=D zZ~cU4vGsX@tbC@>XGN^;w&B(FnqY-FRL<4Tx2M3q@1X!&SssNU_wbDooS7z~Lc+_e zEv6}E+DQZXVm7Xo$YGjPtz?!}UqP_t&NfHEw8UQOl2vEy5?T#1ISaHBSXZCj7@^Ax zUulQoa8Y{sqOl{Dk3U>3IpKNEGAE*malBj7$0PSW;Uc&4d1EO8MJm|o?(6H5Rp3C2 zj!)MxwL>m0l%$IV9z2F|Us%pqd2lv*(70LeRNHiSUgz!|Bmiw@I-bDt27g5m-9&L^ zTsC#7_inS%Kc&Y_^t4QBv{}ulIu7dw7T^ZX*o;+v$-Z@jy!}6csfqKA1e3A_F-_PX zI|~c&+qlLPQ_F}LaQ!~oNWG=aSV6 zovi(F6sYcut$u$InzcYP09`R#j+x1}ZB!687j|GS9u2qxLt865f1?~*jV9Z6`5F%q zVGXa~MX+ft46i5M5SsQFr9b~-#SBV4AIZ0P?tBut%enbZaTg`2zMZffCa?U<;K~T z=$dn>`G)PqH6MX#>t`8{$~n+yQ{JI38oO^Vkn;Yj3T1@t7^)$;veolWwRQX@0=Pek zjxJ>!zQQ+Pf2TazO~aA7Y12xVsM8@?%11RMucG&Adv)H}I~UB`TvS5Csf&7uWXM}N zz+=j~+8}3|GY-ZS?J2xF^1(t_z)?h}0^)}KvTe#vz(kdw3njfWn|Y{RdpEY)O}Zz7 z!LRjw@#)(0HpUNUY@GO<<-t7N=Jn4zNCW+l=bcW;z)Ok}O~+7HT+RcAc6I1_ov$^) zI}_!rwpfh1VN7E%Ee&`P6sDljXi|LK?tw}Q3+Q;JVlm;KDPCMZLUKySw`k+#x}OySv-K;I6^l-Q5N_oKy9``)tQo&n5-+r%#xl zq`!-*dS;wv!ub*p-VHwByBQ~&#hZ?fxf_S2mTrYEe^Wu^vTCtPxX*5oCbV8wgt7aZ zn;SZe!@(hoTOYgizCy6(?N*S$xKw=g0z9WYJ7Zc~f7|cy;<%9jAcuSnBny^cz=9>` zFK`LO1pMO@4aYdjAnOZrmB-u`=chruBG1GQe*8UwB<3r1081|X-)sL($bT#3zgqZj zbNFw!{I4(k*C_v!1pjHI|3u?|^7uc$@c)A|k~1>Ol`oEZO_ji|9k_T{n46PEqGM(r z*eENbhcMC8_iP*=Tbq$nQudnHH#Rl7ySf^hvEtu)3aXbk78b%4%PJ^5cz4|0-D%33 z7;>CiHm|HKFY7XE0D;2XUB&Q0Mi1v}aBy(Biijx3C|z{E!rAKOZoI_2!tXeeiU2_# z9*ydS9q+ojx(s=mPQ2LYjwtMkzA_#&Pa zz43O+`Sh8a*DQH(ySPIgLFLgz@)~^o+JzH=9f5XccSv(GXJ+@deYtE+6b`Z$dz2ta zjA*vx(wODsHJ^^0)snJQ&-vo$nzl{9c_tH7wTeYuC^Rs$+q8x^V|~f*tYOKpJ7GZ3IjWv4zlW}laCwxX?ld;6|M-H zyy-A)pHO1;xaE~A_fC%(RCaTH;R)_m!K1sK5TfZtKp+{K;1<@&mG8i+{<`L}LXP7! zYfeUJD13AKiC5rafu=?@6B90qfdpHC-nJh@QNYFW|5$)+Xkf1`w+X=m^yrA>NH@8& zek2zc7hSP>w(KkJ4^;PVs9ftr8EJiZn#~(aPHnofzCLWa>J%QwEtN{#h5Qg!XkibK z_>T*U{=oy=nPW81pHD8WVTw}vM-OEhwR57t2&g!02UOhlc|+yz=#W!h?GCo%vbOWD zs(8roZe?i3zBtGHB)^Osy%U!HM4`1C7zN74d_9!3NxFD8!8J%%=lb_s#lX6kyzW zme`ZHSZB2}u}+Lizf!}y!vuO}T^@P}#qyem>orJ}3nzM~7vswG=9@Bwsq z;Y5}VJ$3=ndnV^kvBGkTKdD?wX+0bp>tyy=N~RA#TM0uy!qtT~^7~?~mi%qT%L-KL z{Bq3_n}^JTBh-R_Pf1vC{v%NW_%}#dCNJvflVe`CA#X`$W~MT6jnJxL75~sD|JLAN z!=^n3C2-4KGN68TVnfC*q<|qKqAiCLdbfc6f{J*wH&GE@NgsW@7k^f;Y58R`d6wN$3slgO3NVqX3z|b^cboRI*VD6O zwSRLTQ{vod4Q~9ih)r!XX*)<69;ON0cO92!hsqxaC892NsTq_9bq+%eBqmV4^2s=k+kG*V zJtz+Hmb+&}^X0EZU$5J4zPX;buulO;br-a$2H9%MsoSzF2=Df4H^5U?;VzH~SemCp z5uMy#ul4ew;#!h=jCEZ|ko^*vtft3z$5aG&H4aD45rQU?4_8*)CdauQBxkZl6a0%f zXE_6D_n58;w(73Z<6O2jyMxiCz`rb#L^7o9SsYd`?r!wE(FB4MAPYcKz5l+E< zSuWe+RQ|`|F_g^tk}VIUO0E4WD|Ruq1LAuANzGV;5sQTnn=-o;Wb@rgDqYsO`Xmni zPlP=qt1fEJwVxxs8WsU;4ph&Ss?$o`SO1v03)y!Fl&ez~V1ppliJVv~k{jz)Hc~C2 z)yXE9m5nc51rNEvbrcZ`vaX~%nO!pD7vU(uXT^@?mgbak(!-J@tjN8MA5Rjsoy+=> zpc9#GVq)$o)5(FLQ!5*(8vo!SYy-8`xZP!$=s3*z9v@jE3K=YuuGXP|?AnyTl)(d8SS%F55QtL3J$B0{`}wb1zd&Bp6j?v% z*3Ch@;ZF>Gt8Cr5@YxelQBiXt0G1nm0%_9jZc8hxqr=0Y@o}!ypL26_9o{)NH#d~a z+`G4QKz|n(j!CIGotBkkfNlE=Gew)oI7qJE$G&Be(^2OL9l6~E^vZA6;xR-^5goFjJupSEuOBLX( zux>nu1BGw2s6akQ!{Z$G*MSHxSYUqZPU4uHM(;zsYCnDKuP}_~!G5U@1O@IY5hfCaP3~n|ZbnCiuJB73+=gCXn;+0*hZCYBvTzS+W+^{Eqx zW6OdcgJGz4CFP|!#eI!OtHaZr#0${3qYa|cLxhz?puc;=gmsvx@&_JzB>C86K$k8% z>gA**fp~xpKy`wnM~IVIDZ8j=j6|i%qHT z2#>nhi1JuF;T?*Ee}OP?Y^TJ|?fVdax8yV)BNb?}!&^HqAk|&w-}1ynXe@e`H}OL< zp0wZ~c4-5|y^S3N@0nmexGXkAoeVLC{3>>O7;8Ry^ zX2zdf`5fZ4u6YAgTTbY6gieWoa5+l0quz(ppiz=YZ>%7keD(D1pN0*f7mdqThsmU| zeBBYM-2Fd`z1rcufU{A1f-G+~<=A!4oGTdAXflr_ zz3)c9K8c@?SIh177>d$NuGiAs;uGSJV@SOcqsfP3=8>x!lRpErwZ8`b*_0G0FFAY! zf#?Vbo=T_h#lye99}*X(KU{?`z2=aYalqsj%^G|8_5|nOTz?J3$A6YQC<$J%I2`r$P#%@vox;AUhUCvv%bV)9TOh3&mG&(%26P+>9o?x*pj}2*9wyxXsi8+%0t9ap=U8qDcI||>=S{F|4JO!_wudrZiFODoS zUtZt7kr{Fl7CPbz@Se%oV^ToV!$$atgO65C+4+dk=>)k5Cs*M!6NXI0kZJCzUY7v! zTKgDmr~=)=07O`UW1&A0j{Spp1MhO{ z5k?~x^SdCtBr*C(hR|Cdx<>hu<;=-#%@&b6bG6O-7l)U?irg>a)Kx3B4NX=E>!gBj zu>M^l{&&TiS-QZI-sFgo=j3BXNm7|eI2++0V~be6(2J;gM*a6j=ZtG|?Bn!uXZA?W z_<

    Sca|QauHHFHH9_*Ink7M=?>i@UqGKDt4SSIaM9gX?9MOMY?`Q`ZR(#Jvs_r&3=Cl9tO z9rNZ+mzIDoLL6kzen{XF!H+q#m9&);Id~VPb40U_l@s(*>MPjBap&6jbfsvpSL*c! zq52eO(_Bw{y{34xR`TYsEG*k4YSF!mxjbIQMr}cBhkWsz=)E!v-4JOc*ru6jS-;(= zzX*_chj`k1z4N6Wzua!Mw$*y?xDthI`ln889dNt}uDpp+5n-;StaaiFuQ8&nD06Z2 z%&q6e(mE<5y`!*0lp;L9g7pYAGdF^_oH72noK&_Wc%g7*>714;Ft=b}@p1-kZ^;Ro zQ0qn6mM}v0d+G$q=g@P#4Vc(k}>s>-^8i{YWQ4+%8*04(MwYTD4ZR2u2tZlH?QVBBc8Opmt z+*aeUk6EPRTnx5nTaHb0Z@R`+!w4oS!1*-U#V4t+vR1Q~|MdRnp1gj5l&AjsZ;G%_ zO|DxrrzieTe#zgyV>L%_zgRe!F#NGF#C>B0h7l`>?uvR&joyCYK{XXM5lWvsaD3)^ zI=zM7L%hsGsh430leZgT9IiQ_Kbae3D~U~b^p;4H7bREL=eN3QV@XO{EU&N>TpotW z{k>hXGUndS6@~D0mK?nr{W+zW1PVNRL7tMX1u5saP+PCssJ(65bp?(!xD>|-D|@|6 zdN?>79Zt%On9-~`LB>#OewD4pE~EVuhJs3KXZ9gQL7Z8IOmYVKP}qZ&3O?CT&lRt zwM3H}w+UXSoQ=iK{F+S|ZuE#VP7ZfgHeYbH1^@wE=$z4qx3s9O@>_5DpMJG|L>W-l zf)X0&c=Uzfpa2i=0R7;~9Ts|P(WDx!Jy|vgc6CxGJF(K+<$)#rmpFA6d&f2H-Wfx- z$Sj!u-L+eGP+p{ZW=(wsq_V7$Q`PK!(o@@O!MJuQcU#>2b~_vosuStByiq-*P!cxX z&P|Z7v|FFE$-I!=ftlfPo88iUG+*)=k;&euw_HmpN%rw&2C~^@${nN4+Ah|*&QyIt zT-YK|Q#W6BseOq@+vvjk)r3+XM)5CellQTE7QBSPAfoKw=Cp9lG*=GYJv4n6zDPF; z;cs538k8k$*c8})I-g_q_c}@e6#%b`9OMSx0DnRDgYhc%r17S~g@D$ps~N?$D6jPh zv-+8{r4q#gLyZ#Eh67n1Um|pmep)Te_T+e&BCbWf;LcywWaT(4IAb*{n)My#)w_61 z&VewpQ7N3i$s>fLi0|rlEc73T1Mxh{pTD04-B5orLtsXdd^7Eqz2cT~)c>C2IXLBc zy8;>#%>H@Hc;+XyUUfgm_xt2Ib5!@--Rk1oC*SF3mK$~%!!eJBg@tC-Zjlst)LI0I z=7`zi=TvQO&qy>S01-QTfoh2`mnvvdD| zX2T0ImfiWVHpB9E0RNR$IqyN4=&C?0gTK$!qW~K(MfA5fsQ7rH8T)S!6f;q&yr4PXOrM!j5x?xMNd)!vLF9XE> z7p>c7=VF~VX9*6#SB%c_!+&%tBi?TesrXn>+_|ETl^Q zu03Pf`p!L-NB0$mtdD!~JOG~?k5!~SUC&d8tI8-BNwR;SR_iaZt3!b*$7u2*yCZMY zt@_oI!+(g9=d4z)n)CDX4XCZU;*@5J^LPl0+f8)F`6Cu>$hh14oo+(jzngxKH%Wa? zKySkrNw{_#gpuiuJvN`txTUBVb|1o0`CBAe_1f37EVKE0oYbG0~iyM+MHIWr~Y z=h!4+U=ZyqWzSkw)INFlBRi^nl%d9p*_L0mj&=BQ!i>@zv@*+lZ_MY`V` zV1N>bWq7MurLY4gIUx#yF{vL&_;`{1M3++7Q~l;XtL2gSzWvs_O#%fCgq-OpJnONE z8Gk0)x8*wXLR_#j&>i*u`QCCb>t=b`;gCJBA-(7FxMEV29R+6Kp4=nd@E8^8lD^XJ zJbDSA$)$)m=|ky+Szo{3<%68L0A5oa9OtY&TsVLOc9ff<6{~^(ho`GA>(Bd05&Z%N z@7HX1&$0?2G=GDaYqpH%QvpfQGg{-siJXsa5Cy&fKHRE30NlF)G!=`27-$33J6TY8 zEp9DeTK>LOWH*0Yjb{W}cASLui(~7@Nx^~m`mZk=?@=p-79x-tgDPNog(s-N1C@oC za#$$bquXS#C+?)P#BLdBCJlncuWR?7`2yWf%8yOTc<3 zJG^!89eu~*u;h*tETA&s$AC-xh}rfSrO#oRUgmh;ZU7fnHIR)SjZR&N zIW3N=r0-^Bm(ZWxV`)l8KHSZ-l(f;U5{JdspT=th61Z^!X7^^6-KovT2^%6VP|ym; zD(xN2Kn8evbcT--}gQ}ZL`Mt8jUvrsBlX~i3Zn$X<9|9W8-@0&XOkP z)CBvWb6sL^_{{mtIUioW07yAriD}E)fU@%5P!%VjxojyPw2KfviymoDI)-U6;#w`& z5-9>?uf0-##p;8#=I;9U4vW(o0zQI}OZ3Y?nD-u9D0LZDbRlT6{CsEr@YUw|{g{padUKI(S z!#tRY2W-iTIl*Gb8j2xVLR$rJ;wJ@H1d#C6(Ds z=@*p030TA6JmKBM@@p4f~RslH39<}#7Iy!t|$}b6bId5*; zm68#+Ln41cIdrVxTTVDjhTG%ZXBQlwRk#V7i%>zEQ>VxDq~v0BVZV-Dl8Bi5o$QGU z!6JY$W``&k4Q$r4_*;2jYJ}3VHu!Tf%4q$xM$gv5Noh zoM_S?)h)vx(Mca6u#YX^zM!`b=ymuG;$^mP^uTv^$U9mGex`uAJed;2VD( zUmyl49UbJSY(=Rp1o6pfx5Lk&7ILle~QJ zKCdYbnftiVL+@TNuHgne0`K3st;Xqb)w_MsyWq<>{93yHLqMG!54H3X9{RLAw%Mgq z_j;ZnOg}=lXO04~xI)tPvZB`%4xI@<1Z+X#ewTq%Y`C>gGjSUn)%2kiYIpXEA#cH2 zc)6XI`wMZD-eGsyEZ(mT;>_7fUN}9cmpIgk;{yv`?=Kc}2ST0@Bwwg$D7T<~kI@au z-o@$(5FS&Mr5>q}Yh)k&%~raI)!5}x{b2U(&N7S4&8U;+s`TBrpN<=I4o&WyXyFq& z+SWHuz!U3Hji1 zf3W`f4w8d0v;ax6N9)?C06%o@RCGgwAh*WuNNlVTE(*lA0#Z0~aN$vbY!%0=_Y)-Vk1R_#7nZ{9i5<-mi;C4MfKYdVZy9*WV59Sm>49mOQPA$b)bG9ZW5w2Ejx1 ze!A{*UigzLpV(~qGu{-COUQp9srW#1q^+(tiKSR#QxyoVF@5Ek)^pl;c_TQ~jXybl zSF4tE{hb{SgF(RJZgHgc|5&xy^ zD$l|SQwTY>!hlYq97YGwPsJw_2OVQ;u&it&u)Ua$k#Y8iS_B^!!9q>(#zl2yWz0M) zs;9lZ{dbUFF2+smH&)EOcf$5#a{d@+xFJbN3SrV{XioY2 zv)}xtr-{3Q#hgEEb0ObIp_s^++rg24!F^XG}7tE8FP*4gufyy}`$hMfFC+JrnYwgb)bS(V{b$@FG4RM8W*i}NxB zh{M3E+PIKD(1VuE$vpsxZHc**LG?p6J>^j3`H;dwToS>9z^kq;-=`R#`QGEaJCpz? z+YcQ-lMp;pWiF+!WujAA@AFU$86$V0&RAX5N0=!So>sZoxSMEJkbZ^LUe3r0NZZ2R z#u(23OR2}_Yp_b8T4r)?Hk*#Q9KKYE=7zSql~zPDp{due_(D6(aN^kH7$RxHwhTY$ z$>nvLGI)jyQz9?^yHTITH7j>P+zmo$NyPH_kID$jq%gp(G-Nmg zv=C;4t9XsxOe7D*U4HM$--F$=S0@j&5#V?C7F_&f{&AiZJW&f3nT1)84dCIr3XH>x zta)Pkd7zUqp_^a3nr8Xi*N5ykRUzlpiqD2nK4`7ZM{aEVncJALhih|FH0&fQWXD{; z#_1sPC`nRm*HMxZ9`BS2hQ>LWx0r-ct`7kWXO$l8}X{xiNuQ&6$-%>3o;i=EZV*rBqnZzj*`dXu-cUXA*9& z0UE#rG7_?B%GXkt^0~6Hv@%z}qR&5L5YhGOH&_ZkQ!*v@va=h8S%dUT-*eV8zt`!iYCcYmjL1et7KrwErk@>+j3Cg{ zuPSZ*(-@3tuWG=_mZ2MX-P>y!R?!ry1>`ggm~8HD-|B7>4asMqq#J z>ofkV*z_yjm)+)>_VYaLwXg9N z+F0J=U^u_=twTVfezjwz8PD(KOh~6$rW6*u$&#L?ZPK`K+_+rp{^Em8lYG}%CCN_{ zAGk80VQu3hz${5gQ;$yd%!yQ?ZRc8{nc|p|UthPWYwOm^-D3POfOgj?DC4?L3YPCd zV>ajEYcnK#>c#L}YjC0jw_r!KuRscbZ5=^-D5e^r$5nXFfsZu>z4>nxl5qG zTK<^iz~^q$?G`-@qrs@?=6iZlCSJjhqh#k`p{M1gW4*m^u3gzm;aNQggA$)1TB-k2rj`f7bmA-CXa+Yi(;=2fJrT z*p9oh3l&c@Lw`yJ{WFQ#IsgmW6LZ$L)w}pv&}4xXs1=&R z{OeR)oU_U*f`@Fh$YU)Y(rci}gS@jbMC|`8MGq3DUs-5uS%ic*sCOvV)6^X#2h&jHDSy zfuTPz85NaJX$La&X38CG;9vF2KOp*o+#zE1?+FeL(<^-=yX_tnOy|pB)6;#ymi1Z% z641_?4zDAITb%G)?Bd8+TSYv8ejt&T%yjsaAYKf8jHnw=JQDh_O(WpakIcBr?s|xy zj`rY4<)eH-$Q-u{=}l&;*>&VPkWUYdlh9&3(W{bUUbq@f?#6nw@p?-2^14g{HkqSE z{w3ei#~);c>dkreTVRe-e{uW)H}*?9|Effn{(K3zu)11Mcazz@SrDR!l*RJHNJ+h@ za}!JbWaQo*k_gsrMt^~Hals0zR)*_CacfufR5I zH7+0c#Lu{s4_ooU>b0&NZzucv8x;l@F>To(!)FiQ@$W$tFVRU1Sle00j;4oq5CVMM zSkE&Vo?uXN_?h!IPWBXk6hyXN+_a(@0AQnNwc``2=k6%Dp4{q-ty@x@el6hP8#QFQU|?v^$ssczVQo3#aaes!xpvM-^XSgn z_~(50e7A~zr8ghUz$L3iS^zq4Y;81xy7Bhui)sH#pO&*fyINK7=TRBFQMWf!g6w-6 zGh&!IlN{_qTvRgQ#n(1B=dvF7(TjiYG&3;?I>7ECqludf-puCRyC*)Eh&8{wrt4Md zkz!PgkP{G;WOchP_;j2bP7VHSc;@}GwL@z`Fp&}Ud|BBC9gCXsDZMmXK2fd(UX@u9 zvP0&HTfS-!@TnVJd}fkAP>d>^H5D61V}WUZuqZAL2v{J>EGrmGmlp5IMyX%^iLx9)in3pg;2%Y5bq1jqGC&zz8Nl90w3Zz%E4dJ6J7f2Zct zy_AfJxi)N33|~N<(X1UA7a-=CrNm5pZYvBCInkm6boJIpaq9>UX1g|%%V7C>Dg8;l zJNyPKYn%#h(N!3pczdleLev#$_jyoIuYv?p&87AQDgezgwmR zx0f&7Fm3%is?Ie|7T*8x?PB-Pgw#`pq<`&dwKeKsSUTk|=5UGe`G;AI&74KcsdgH< zaf#!X-)Rb7xLR6LSAQ(Z6PmQhy<;j{=>rFEQ@MYUKW*Gsw9ek=bqnC^*4U0a$_ z3jJVvAXi*TGl%n_5hSU~#}q*T;jLg!oAPhZDOXrK`Xm`9iI1Bvo=tqsKxrYrM7->q z_3m(-ofF?yA`e6R?t`IA=lh4TgH-90!iYssNBEJTdBLj(5zqDjg^VpqGnd$|0@?3@ z$XPs(i-FAVK^)Z?;*k&bEB8M%4<^sn(FTv-C1Q7<4c6CV$>u4F)HreUh|k3^x-ZQd zoEiAv&jw-;^EZb(qy1(#@7}y$y{W1u7}{9waRPQC#OHqCSwEKOW@MyC{l>>}en@5l zTPV4rXT+AzS9O3vki*Nz9*>jb#Bp-H-ZoJj_YOfhG5zKvgw9M-ti|H^$_lm+~%r z;OZjcf$lI7)LwMc5?Qet<7U8}AWcPRYg7qq{t!=%Z~Wu3=MW}dfXCWI7KYm!5-|dJ zKKarKS&mv2E~T;gB7811Op<^!|8rQ7mnc*~)3--x%}|)S-yzkC7-4Z?d9Y{!v|N}Z zT~JPFmSt#n58)v|)6m|l^}Yzt!=(KZ%T3%o-rfYXcLwv^5O+x_WH?vXcMg1l?+llJ z>L2zpLqn7VG%MA#BGML$f-pi~Sgqb5%Oxeb$!=s}$Dy_J4yvb0tU^<3$9Z4Y3T7Jn z0DZ|5%F#L6cx$xzMiD`;V+INF`$hkhAHRoh8Pw;p@ZEdEieR3~j4a(K@3Z{)zA467 z`Mle}NlHG*q(8K?m8%E>VTJ$v*|b8#@nuU%vp<>xc3_30=2K(u@q`6ec{l{Sv215E zwJYtIS1muB2G6d5HtUJm(-%dH895>(*7`3toC54Y;Ifx6v92b4oN(BmR)>`)DkMp{ zZ+Q_yyH&~4nt!~)t?J7?=#0N8T7QpA79~etqma=ilC>(~^kes`^F~uxtAs}rtO}-7 z)9Hl@|C^$^_R?M8`Oh&yB)l#D4O#@#UiD-ACUtd&@H=~A`>Fr*l=}TY#+|I+q#;R+ z;B>vC>Bne{PTkPftHnh&WLuvLg0z%M`yqQ}!6y^&L!-G6w^UbU1YZ9<pBN2hHxehIq?1ZA~oGnzMlsJgIFD-L!&ZI*k!GSZcYXA+|&0(X*+hX>4 zJwA6qW7(E>hvv$M5oyfJ%gbVSPe@Je?nk7V-02@!FEWJKaNSrTXIuCCr;1UsgVf_= z)rD5|axTJ{Dfj=EP#4a|7}cC%$i(1CrzvX-XR@^0BVnpT4dpvJ0+nL?=<;A<0?quJ zZD@#hY$uubU;7srF2tRdl~q;X6)*&Lu(Lb1;SM*?cF3PuN;8h=d?0w_LmwZ5)U|p! z9tk>;4h2v;F%MdvuY#VcZ56wCREqiGZHt25qI*Txh2euq3=KY?opr94jDDc}(m=HA zjb-GJ{9$WzZ+<{0`}kIu!H|!>4Fj=NmOIUYW$=)PPe(Qv7n6;{pm&xy%n7-3%MyTx zd&17{#}TWrHDe;-DdHyHB@`=lrTWZk{+;~6dC5QIH@FS`@?)zUrH;l!*ZFfl>|M%Y z3I5qPQx+Xugd!t$CsHZB&yrKYV)vRR(@aR%$^D~yi$7*l&P>JWudZpL$-c_`Eq$Y% zH-F7Q_-sD2=iIua+P$g}x|!>u@{lWnG-RBB-Q#(Ugv!I0ImJXwu0i%IJ!%7$o8TjG z4Q=J!5pu_*(?4)xWTe5$OUD%B576hF-MX!KclliyEA6=c!6P^;>Pfzb*QaPzmcaS0 zFCuD@5|L(yD+ghSB>vU?&{8gFAAJztq}jo|!>mYvxV6H(_QM0xma#IXj~9=v0PJfG zV+3uyX&btab_uGfm(GS`t(F0TeBQ2wb0Y|g8;aWAaoLsrSEzXB(^fhr2n^2*2MAv9moLX(} zEIO62;|}Y5bln=v5iI?4TiF=ZrYlhh3v#qW1}f4Jj2Ase?!Ycr-Va&5^i_Zq~PN zzSN|%_nD5!$@aqQ=rSV?<8x0VPQ)}W8Acifx0?%?Cs_;lFjLJ}_K(l^ZXQS$x<7`h z30x70ALQF{Yicv%rH{iW??l7}$Kb1}+j5FMMXjvVLd6Ou&Cz|`4?5D~t2DFYlR28& zddUAZh#f?MG>HxIO4pCOn2TTD(UjNf{0KUb@Lm7Qqxicm*;Y&?OZ`MH(}waf48NV}MFVYAFJAMDXEVQ5SnUhLI$Tcz4-ZC->2uNx%He&#)AQF(e1%NAN zWWfe1f%C+PKkP)daV>5zXva?b@fOz@#2EXzTZ_tLEJYm6l+0a1kQ% zM<4aoG^buY#ULWeZ9cS}0v)QIy3ry5V1exkPfVKjQD5v!?>%P`x}~@B1T^1}&d(4P zB^5rVk<=_p^3(W_DLx>g8{B6zgh=z0g%>rInc>z}4r27G8-XU`$1 zwS0(9G|^l|sLhi5X?VfSIa{TPRcis#jTJl_laC9tDBDZk3I6Ju^|R;aW1RcGhauEB zvSmY&K`-B(SmX&wkXm(ZQtnL zkV{xMO`9qgoSF3Jp!Rs_zom(3SV8Pwdw6?0H@3`Ss;4wC7{2P>{J=Y}58uDLY0N%h zNCIb%^W&BIMVTc9+i10_^uWM?^vk*InZVCTZbwAU3$oyr=ZV=IxWoik$BH|~~c&)kp<3`EKAesUHxs9f4Rml=Fo zK;DR$HOW&bCq2&5n8p<+@P1?Co%_TMCdx!^P1nbMRFYSjbwJ;D){A1Jh+IPH>&ZV@ zCu!8O6s>|646xUY4%-tE6-@Ro73Ca=5&1Jc&y~6xhG$6CekNk(_M>mk=QJhRg7tE9 z)o-PV>EiI)rzKo2`!u4<^f0ubxX3i$=2)t$n{P!Yu3!K+D*0ixj`sO#-QKR*=vVIX zSi0l*Jpas?F+0(YpklR*tmG!YiHvasK!vLK=Ur#WU#^xe!mEOmNB$H%yc;ocwqcsF zX!t4wWaCxoEDMS+XMBm+B&35gq1xD!)m6+WS1?_cl+R}x2?LN_i80NIvwB3=4mdV_r)Pr& zhNH4l+FurtuD|82dl(s!6SKi$De@gaJ;gBk{q55}jYS-N{BWUt96^DnYc&TLDNt%i ztxBPVY8k^6)z>qhnJGU$`+L`6vQaN)9+5-y&Q;gh_P85lraUSN!+csa3-XYAeI09v zIo=>R_J_>K+!*?_G<2cfbO6;>WN4tgwfBz;7kRQ5i@E%dewT9t#p05hrPzs)z!O9b z=m}qTq#$GJRB6AF&8f5QEeUf@4}&&uuK9d+RDvD#UM{tGfb+Q#78moi z0uj-B4?plnij!U`R__Umaag}T<`cNAjJrLmsk1l zSSX8?`-@9hKm>rkw$bF^PpeBtAr_5IcMw=sTcP=K;C}Jezub5k%10bv!6$)rrf6;(A@9oCFSr>fi||>|i*|m5)HhWVi6|i#qh5u20;crW zrdIZi0{8RlvS*mGhwp`4&)9^aqYC|Gz7(qUlx?hGWc`C3u@6jSsAS$g{we}! zBRyjE9;Lv=_#1DGT-eV7#6%u?EzSxZANi5Va0$%m-xCRN$dc`5ZOo}yF|dEMZ?z8y z$A96WQ8FffXwXx-BHDE?6ASA&R?7RVAd=YhF!b?h6t%*$yOe2bE|^Ruh0(NIWB2sP zLz;XeoojCT1a%@4q4YD}HYAcWBTJyF_t4c0ogRDRRt49{y)!a>P;Qk^Cq3He*8umI zU)HjFv*h=5>-4p>#PfO6o~j2VjGHgSsYz<)joJ;`2CR?retvhtKa)J12GIngNM$pCx5YQ$T)Jm%z8ZozJr>$HOLeVIX_NbHn!aJ%|0JnU%lWp zH@d+>|Dc}X41Ln<L6y=) z!_EC%HdFkE#omE9--o+B92FY(8-g9+QL`|hI&`JIw zUm}?899URWkz*tpr1^V0R>`On4_V7>_yxEss=3xjGSyPYWPTRKFsG=MhY(7x*hcjz zz_>QX#+VTFgzi_Kodz=&7Zt*3F7utL*>Z~?w+m%u+Vi;T+p>!uI1=P2R4A?J@}2>? z14F?5++VnLDi=^%lXWU77l}(-X1Pd6wBUPr+evH`FIC&uRul7oi$(01z7pKTNMtnI zUvh$Xuns7|#%J2X2dC#aRUk`M|H2Zp36{UcfTh}+aPUfxVt74=`o~%@6 zOu1M00_y7Wd+0)OyvMEv&H|`?+1mWF1Qghp}w^O8{s;;l%&I`=x0xTn$If3SaGQ72}d zF@ArRNay>?Ma1n`%_RzKX{Py!Z_S?BY7BRQ$|J;d7BQWV*VL%@krIk~+PX#!9h8XS z=M^Fmo^_G_swe#!cJZ8nK}Dj~|H~Wyq`HQPfr^W!#K6YLXi|*B2Iwi_oNpbTtF+w3 zEn-A6$ShQdLio^t;2Fi~n$uQOig>$+GV1?u_0~~sbwS@~ON$gOh2mZ)?(SCH-Q6{~ zOOfJI+=4@Kx8lVM6n6_6+#x`aaPz$PzIUzf`#U*V=bW8Ad*&xI_MA+d&%urXZ|>x5UM&aBV=DRnoQ|aS1K@m13*}l zys4qTXdA!~Pm6p~@=GUAs5_uxn!=*}5l=9M<$XF^+Qnh$-0)XYWWb6&popr;m+xsz zNR$MDhP4qFMV(J{-G3W^V&=1a;Gb zNk@Z!I^05i8sE3fVJhv!8Fb#W49gEfO`F@=H$<$KRiA}$T0}N&2OaeuW!@jxPZYt> zNU=z~0c#OUYFSyV3B+wBHD}c6EXtHw&n_RLGRQF#-r+;1;N*FE19r$&BCSe#vNYKY z0SXse8-gg^v9`R}>COKBw);Up@4AQ$Cdgc``-`%$-L?c1oLJqdzASiz6(wmcx;QC& z`6@jL5#`4SM3Q5cZuk6QjG%nU#=v|nZ28>KHsko0{kBQ06z9+h7cH=uZ#k7MA^s^= zKix411Ld*aG!rfb*pT$d)cF*inK|&rB!5d5S^52M7OQ=?r5UoLpV9=ao|wC<5^&n^(SU zwzM)Jhy;v&qUYwLG5of3^6VY#5uu{iORARdn)dVZf3X0o%2wCt7Kz}M^*CFS#czuI znDNYKhiq)QH{33}RhnUusnBHAAJQd8Q%E}I{8XRcnx6`GcD{2FbdQ&o6(|y*IA}OL z`~$GIFq$;NsMvx=ZNWh{oUNN_%pQQi6Z+VsUAA&IFUtO+s0@u(C-q zk;&OXl9QO~GG8StR17H}AX`W35*EH6Hm>)YMb9+8QztJEZ{m={V$y_EQ!rM>sf)2Q zwzE^Li#;r=1l(o*TyS;pP5ql7neDms4YK}_%#X0*HmB8+y-3OC5B=rME2dd+6iL)+ z?JjYq_{;Sl`tqfL3sHaY*lQfA!Jr>|(9CjF`2k#s@Q(Da*i)F6ehW=uenK9Se;@hF<;C$4S^a#X1 zQ7!|i&p*4cM`w^Hq|_{Z>CoOR%R^Yk2S?ekdCeoGW(wTi#I`h~$SwguhZ z0lPU^rr^j2B0MGkeTvn*UBhlCwP`B+Tw}3mjjy11`*3qchNUPFFH5VQ4>!R?kL2fQ zQ4(S}cz_4Ko7XMb{%ernv%S}riKx%&7>{XvGN8AA<`)$KYBiI!4OI?hYT-m<4+cdJ z=iggB^Me@NH>=MNmn)BrIA_g6MElXOOGOQZ;FzHx-2CaHKAv}TbrA4x&aVt-oKcVb zvj}Yc?{I#x8IMw3{*a(-#c=+GTPIkJrgD{oJh*4>Z1}EJu{_|peQ-E`oK$DUM=Kf< zp3)!4|M1|B`}V_dzJ-~Z|I=|fj1#Ui2TL_gMeZQ|K&w2D2-glIhCUC9g#6EKwF?qd zU-_J>5hAK82hJ}?os1yzLSL5OJn=vSY`te1$T~kc6reWHZ>r)oKLmsct}3H{g1<`q zZlYi^EM34nzN#19gmw01nyucD$ly1!m}7GJkMB_9MK6llcBd>tH(ZlqS68=~QuS)a zrkB#x$Y2!NtZ5(L5Cwyz>W1?TJOv1xIBz&89NT81)Za*VGOC5lp!5d5kME&SkI;0~ z+1;I*^XQ<*9Qo~{`xLpT9Ytc+idyx#D4U!cM$*bPdUe2$G_cp)98o^QY6u#Q6U`VI zE-Q^UThg}V*%g3hG8nU&Wyn{xB%DcT=g1H5)?*}|K%nYg|HrBtUHd3JsE`9 z97Dziv9#e@ckIFM#R>zG7Tbpon zmQU}WBq@DhbEKH3zpJ}RS)`*!o5y$6IyS8c(d%!{D(9n^L%wH4bbfrNGPdIWh0%jT z83ocCAK!IS6@fwjqx?bjW>M@7vF!@Mb*AqZp*{-ZWqdDK)32{K%N&w+L_80UXvD!0 zkYka0;!Nle(zMW6_Ch6n57m~1>DT46S~0O)^EXOq zY-lZUbWDJo7CCuKBNi!>9lgQ#$IO_KSqmOP{D`%U1*g(|7q*6`lHui~duFV&8N|KR zjHGqrGr9zbZ;~$uLwgC&MzJ=Vqw2Hk^{AJBc%|BT0To-nBMTRiujiLdQ$BVOw`}*^zXW%H z&tLhRcQZRd)c9Bj&Rn8o4iM)j<%tYz+ulLbBanmYB;HS+)HJVH|0;V5?fX$vQwZNH z6um0}#)7SE+G+3cK8I+hM}KDbJsoE}R`2)Yzg2j9o*WSIq$SbgSBIqJ;T^%MtnFHNX zSY0=)xGw<;+ucG%>>R_HF+IuY&aGFa5e3V~I77gQH8t{}DDd_j!{8pMsxHwtAeD5p zwYlJGy($}#RPD;B@=VmhQS&0y%%--K#Wx!-eI0s+3;OATrvanMC5ciN7x0FX{6N5+71*ek7lymAID309FQi z{JM{RN_H{oM6BwU2GKO*r*P52pv(s*-+OakgT%WzmRDDU4oIDNH`iTG*=z4Nm$DW2 zcX#|C4FKGUSVih+NKvdrU%^R@@!>j~T{2{L9DR30LEovMqXTlc7P{6-pHGA($aEI5 zS#ow8{3X&OE2TtM}PZQiOx=$_$ko2{-4r?gy6KAUM54jCzJtloI zI|*P+ZvzE&;-=wGdt8qab%P)~!SjqwAb*qMvFEdZbG@aLIz|9DKmXl$9UGa)&*AMq zh;18?r$4`x#>!kWoq8YBT!$5FCh%{FLX@k^N(p&T-V)Vd04T=VUQC8K)YV_ zW$6oyB~VK0U`}Nv*gc+wm-q0>L*%LYX+fvxA``rq;%W>rQh$e4c>_IQD$BFaWS8{Y zhUNiMXEN_PbJUjY{#hSyDpQ9HnFHAeI&G6uzkTwz%D6>-{YB0>3_0(ty$8*G#-!lC! zmTRJQFP?q%>xE`oNQ8WUS_6#c;Rsvszo7FYEN$c~#`RPy@{|F37oZQjJ|{-Mrvq+h z8X?x&lamNOO87wX>YAa@-Pd#OiM$$OVS##QQcwr%1~6*bm>1Y;w3!h= zWlcTGt#U6B9Q?bAkTmb0lzd)m-R{zj=y1$1dHWXG>#tIC{msLg+b$qb6h?R9zj|cH zyKX9QY3aJ@o))fRp2YS@;rw|bG;UASr7Eot}h+xb+fwee8?J!r6p^?nJUYF+=qS7xTZff z_I;OwbYXTMRDVF&^>vYQ3Dx>55Ik| z3rX)FlBDR+P~@4|Xgsg3Cwvl;@>Px@cR)BqdiB#amHO`Y2)A5jQ>F8ul&_|GdX}(=^T71KJ_Yc_NZC6l&MIVD6;5u z;bJ3$xLK*Cjtjcz_3pWj0k6B80j{o>7F#!h3`}>2g$)iN!;)B#8Y5!31Hmus3}44! zl1~zc7Q^=hW2x-*jPm!n59P0|p!0-p_l~Z^F)~O46ppIX)a$n%Pv4e`9Om-Aqw>6 zO8@U8Dc7pa3547mpm~Dbd<-UtcM1wN&n?CvM|~}7_w5*%`HR#c8}@!p3V*l3s|QpA zBCu4cah;`x5WLZqaI6sO{b;${FjA1oMjjXko!203+XVf#_RJtd2oY0Knj6BeNF=<5 zQu*N{t)wo`c!*q0P1@w~DCb%WTz#7>jI@TmTt)0AXo+x>`U4kj9WTg2PO#5@QZC+1 z$sA3?{=A^{+C^fF2NmWVyMQMSfHlkv9Hd^E;8XWK?comna}Kc({ryajK8?d>SoRtNZ_K5Z z9VP64v4E>Rf25yH4PgJprXQKRqs#(Ew?5ZCyHk+u5IQ-sk@5wi$9aq(HZu-FERp3l z$1Gg-%Ch2jJgC?J`gIuA+k!_@^c

    hby+k)#rfUJGsHZ|DdP6^|O3V0)SR8>`Ywr^t0+<=4#s{mY?zu)$>vNDRy=0yH{{b$ih z-EFHrDy1s-*%-&OSm@?pbaUqcr$d>tlWE2f zhy*d^^GV63?7c|-`YTH#U2t~JF<*al8?PuEWiJUHxuo474=@!zsXo;)_UwVAOV@=( zr|2qte#HfS{a1XnY$2Hck|7;w)o!)i=}7-N4_U2>%CZrD4ZS&QlVE8(+lej2p?Qz^ z;&M|?&ff1ch<%-~8Ca%i2(bc32@!r(^6I{6?eQo#+xe!6Dq+T|Xkb`PE-(+(u3Li! zj_;L|Wj`90mOjp;l^a!wVzjgs|1#x&atz27bE*N;+B6w;beZ4NlIJ9fitLiV-Ui$j zTDD{-noCJD(F%QSjn&Hm`(Ma)Q_sY^bq40}QeNj@oi@QEjJ#B?!!im^&nYTWp|1)X z%7T)-LKu-`wR~57i`F^Yz@EN2hm%J;+{_cbfaGtbJki{2t)d zULWMAuOFpk8WX0eTLX7MwdCe5kYO?W^Fceh&T9?uLvj?A^aOImB95%=xP8u2TyE?; zsk!o#@ybtBWBX^5AAhI&I!o{(DM%Lh9%(&bUhQt2b;LlZ0)<}k`B`Igw$zrU)i|JG z_t)k&bM}w5d|!P#!eQ&E$YOQ--dm0?$i?bH&}O$hd0n%C^TKC5^FBT+RAXIRz89`i z^;PJ6N(Uv4?TGXiDlG)CJbksC=hqW2wFPADO}%uGn@MvCkXed+Z2@{Tz8ss3HPq7P z)xSP2QI__mEUo$7OeA!kH=6jSJ$vfw124LY2cef%Idz>ZyFE|Sm5FVaUso^MX^lC3 z@M92LS5&PF+m&N@^B96UA_sXZ!DEcr;CjS1l zB<+Xm&Cs$$rw(-1_B^f|cHmXRKy~o+^iLx`rPbX z8(*%&fDyO(q;H%#qH;Ln$NE3TXg^Xbw$y!txHqDb^rnO(>sxQK%66SCTaIPoF+IHs zHgs_qf0s{847sxo5&a{dwcoB9S8^ET9cO&nxt5pTD-z$3(oA-P-Rqe?-K8_KsC0FL z8^=`#n?(0J zq?@^KiSc52XlZF)?oc5@N*P}-Wt#uUMUN~ zgoq%n5{f;~eC2DB4sjUQp>gC98dbgoUa_I84A@Ci(WHQvs>aCYDrHMZP<(_ zSc14Lf%}}V67Ao47?$1JH~CI>$hxn3!q>u?w0H|cD5Opf*q=fY8&(RqeF$+*?=G|k zBFtXfm4*?P$W+c+Cy&KQqy+<{(FQZhMIvm4ErY3h=eqT+W!0Dj_+weSC^ zjzn~+nGMSbF3WRiz#%>BmJU5mEQUMX-qg~Bz1^t>Q29)OeYZ52i0dJsU3&LhCn=g! z$eYR??2$ehL18kk=)#@vu~}Jp#wS~HZ0Js(2=1Xbl*`*(* z8zYuF{S432*%Y(qp@X8OJ?0{h1T~}cWZeBs^NXuK5~3;!2+f$0@RKb}Nl6IKA({i6 zaaY`_=pWa$DCXyS-1JcrM{d9w>SOi1FH}giDnsyJZ9Mp9s7RY<`8om62XxS%{mSua z#J^Z?uki-;y$r+!zZzuZ7B}c~>pR^=l3y7Kkoo<+f!YM{yTZH@S_{NP-AYcv?iY+$ zNwI`%2?WzwpR}uOJE7j#{(aGG`Cc78U53|BM&tq0SBWDjS7%BiWH!Bb`q5hEHTbZ3 zw?&oukB+vsJ$pN~v7=Mo&sWYQ+Qm!A$0uvfy&Jtf4%OvH;W(#DhHJ1g(UssA2g4>I zv6mT{)V@1mYulwnVw>(ms@;;&%kGyd?bZ!Xo${La;8e)!Nnd(;dR46^&v3SwyZZ@i z?dmx3=h-92jF*2NgV-HKRR29R7iQ$5{e;h@xRY{%_jc&dDVuE05xx@&cm~jia1n|~ zxwySKo_>X@=}m*B0_-(<>o;I>5W5kecG0$Z$#gz~OvTv~1G-FCYWV!#0qi@>W zx76+bSszq&k2bQ%<#}%oDWv2&Wr`R%G)3wgq*4FOV(msJ=k~+b-CA_0lMB$51QR@a z_B^o!6Ia(^&Ce4I$7=v~)xWA8p5E4(VC}LJ#;g0RTXvzJ!O|GloO=lOjVA9it+Cp{ zl*t`k&wmz~KaK1Bux*Df@BW^Qci(^Sb%E)b|Fr?Y8^dUr*H~2l(?j|8yGk07@ScZ# zvg3p@us7GNd#k@-=>)d<>X*i)!y6F3J1Gd(Y%&WqEA{PpFyytAy=8%MJNOG!3T3I$ z5opSM3^-ZL!V>LTbJet)eQ{WlI3Q}G8Jx_clk6Pb`~5_=8%KEMOge@*E=OD3JZo)b zcXpRRCwzYd&;sB^t?k*}H&8`tS@%fso=L=w z{Bjp#>MwY_eSCWa9E7gXSQnRos71BK-jJ)`{-N<|-$EasbgyH{T!?{4MoL%THyXO` zL_A!8xqV=inrykZQhQ*9(ps5Sp*9r}Y z4L=wPwpA@!k|v{nduXwR`DYJEsMQvG!-Nh5FLagp`n*ORCS-3ZN?C$AY$s^l^D0wni z_}wl5$cJ5LDkF2?P`5fM%!+&LMT>pV)~{F85@>tUnK! zd9$dfKsW3v1MZMi^AR=(|+O4$O;mF_)SRlh|;2l@w={?4_A z!vPTh#6B8av{-LP_QAYBPVFXCyH5<_Trq;g5Rb$YSN;Ec1k5o{L1)l?VgiGgDD18Y z{50P~JfgeFeDdq5U#IK5sA)Z4KNzR1{?|)ny{!++WWaF|gS=4EW#;I%#)P$f zLsN(Lj*!00y;;qHlhY?xk8*jY5Z*^MtPktQ2-f?P6JZFXKEEUB%XS;GgZ-Wt+@wWM z?c4LD9CMsE^uhBYkEWrS%%@P8L}CaHGhnIx`kF#ExEeGxQxN|~Dh_$Uv)9DLxNscP z#GPWxq!Vu}^0khYb;Mev>xa8IPBS)~YU8Aj@)4)*i*OcJ3FU5aOY5vg7f3C3xI8{N zX)v~E8a=9uQIHTJU*ZAm>~xL~gsHVmPV$fj{Wiom4d-f5u@^XXX`U^9_)d1F zg0M87=~yS(O{Twih(VX;0refTZ$Hfxk|J{rsW)U>{yZf~G6hbJdKpQ=X#xm)m&}vL zu{1CTc(h&<8Ji|OhM530{T6`;c6D<6{w#u{T1mq=Gj8!4zlhbx3}z@TKzm3|#VFse zA;kP^(5sL+bs?Qzg-&x)2ZjoBITH>2zgIKDj5cc(dWuW zpZo%QS{xpH)qWRPCT*PZeY3>81Z>y?`9}FH1i0cJx_E?GJA$9Q1`#mkevPhrb)-ta zchpD0z8={jC+BAnn<8HlRBL)bg3hIyD`#$rms&DNKlnp+8$68}U?|l@L&Ip$4 z#cO{`9*FbnQjDOf2kBeEs$0Dt7tc;rwY9l_m*Q^0RcUPt0{7|%-JuFPu|5nAW;0&o zU@#;y9bh-oe@Jw%CqIv zV6~X%skrdzf*%%6(!cyjJ)D7TYP+&2Yg6y~w)FXFli&zB?2M|Uste;vLJU^bX98w6 zroZT5)mNA#6gE#%?%zlKe$qdrbq}xj-PFI$q}Ldg?`F()!qpZDkCq`*;OwU z7i57HRt+n%xEsDKSGEXRI*7Iiz4S3Mie{QTZ5g=9gmtpA<(L2|3U16*Hov?J?+q%ZT<5^{q z{cd#o7Gjv6-PSrJDk~pKJV_FCEDn8;cJON6yd2EFP(X4US;Gb z_CQTeRJromgzty*g-3!w<~+9KzXP~RN|)sCUmS7C zD$7KUkBNXe&J2G!UayK!Gid9BbdYbKPXV;bBs1KPw)*Y6J^6{sO@}?YtM%QJ-0e&+ zP~!W&m_IjxN@uNS3z`0yL~GT#7^FKVYp5=8`P)A8&%ARVw(1TTrv{&O zx;q%ZYGb0Em3xccj7~DDFuj0BC7rATJ0@IC+)w6t2%isPD@Q;o{-bqP?JcE4H_2aJKX)d2ypQ;NW^+IJr{}(##oquqadc3MWnsSsi&xiGd<9}Tc=>qfNz~~(WlLUVH^t!*^xV82o5<4F^e}Mz zRY(QSHEWWu737 z&ExLtq}r~@F^Occbi=G1@6Mq0=~x7W=FVrsy{!d6W#P>i+Wp(|8x&di{RVV*v5S+O zPX+^gLfY5wyKwn=h+9mYYYDTnzpD80ky9SWTNj^?I&@;NOx6=Vgo?8|Xz3-Y0_RdR zrB-vTKZCv-{h*m@soxQ(0|I&*{uu9@WXNxo50-AU2C4UPmGAVmr<{o>yv z1E9YS$M-FQ7F_Po;M(^<*JxUM^#<{glB5KKNz%fup(aSbjhitk-?q1*Dro*(s${}> zCiu4O2&J7o_$g8Tkl4_Dm94q9#p6*K$btro2Xr0}vj*vTuK8NkfdrrsfOl~btZ6r* z09Vz1@_DZ99C&?q&&?Bio|*-PncDss+eF%|aqPEvnQz%uy@`AYzUd?~5mPRXX^SfA z4SL#J>RmC)bn3Z`qM8Sgzlxm;w^yu2yORotJVA-!oq1;yIAp6fbV#-D5_Ft%pGS)x zcSvq-W6-&{=(@v1OjccnK9oM(R)OPXR3^m@znIJLY0y2nNP5`W*{$-uE8|kz@CxlK zm^(th<4{UA?p-R4)-Ikof~Ukn5D#~S@+Qeu8(Xel{O)@qF5TJaV##q9!$|fH9r4!j zKZa&SNeht?ijCcm8X6H873Na$8JbyxC{Lb47^Sf$nqb!#Rmb{W(>!r(iUNisb?M{Q zIE9|?{Y{=5AGyNEB7bco2b|?>yu!K|uNFIUbEUiSl+JxzY!W8FQ4saDrmYF2s;K$P zd|4k%I{G}s!-f4ttblLLXzlcvAlaes+}2aDoZ|)psA`{sO~m|akUZOs;I~ek2yHj+ zY}$RKU2GQUBm#;WX(pBnW-opOhP{DrJ&wldyW0`L(rzS{f!}6c0pO$0N52&SfxVsW z#fkJ)3x-~fAI_zfQl6sZ_=i^9F0X4}9aUqxoVX_~%J$Rubf?(}QGby6*$`8|tjs<- zwfI-w3LzyGLD#^FbqyX?0z0y=+1x_>ic@R5{#Rd}t;APArYH@y6|UYZO%=l)58FLf zfjQ~Tx&G72{u3A5CHI!-YPG9FAymiMFJl9B$JEIv5-?p1F6czXN zhjlA_)X#XtT9*#rR4tJX4*w%VM_@0nTV1lnmrel9^Xu$BsvnSWZX32n~spbPKSU_rsUuD{1Tkp4gdANf>xao6Q6Zc zqpoeqR)P$x8KaY^x)zg%>)Nj2N=HZcaI+aZ9S;E6Ua0{`b2K%DdA9Tn#Y(cYaU8IK z{DMT;wJ^8dB>psH@wDI z=~(YocmAm97{4%Hchk0bkR@HnnZpNYI6aAJY5iQ;`!kvQv0j?hKp74MIy%PM@R8Ip1xh$!;qKy zYb3ip;QbRt)cqYsb5&XYrB-N)d62&fd|?{8fi*uc&?LXB6LJ+T4Pf!Y6+Vse!}j30 z=?H<2P_gUZI&$)-GVcxa5d^(#V`E!rXnr;aZ|G}&gzp$ulv8<@W=`3i?m<)d-GeN8 z%DUH$-P$FPiUly-8^3W2|5YALXGVEj(D*&${^_EVCp`A;7Za_|f#|-9{<5e%7xdWX zBM2XgdgYjVg~fYl`9DprA)4BOZ!1>GS`(!Tej)XAoa&rFI<^OtBFPva%lpVCf5@lP zFw;^b!w0NUnzAtYagBNN-Kz}p=)Y|h?3Ggpks!a6t39fHKAz+ZEBf+=@(uld+sNpB z$@sX2x%K1Nj1Qv2$=*L^*VYRvdlH}e1~ugyW9?t8tOu^1EPn^T466Z_GUB-=vuU0% zO@e6}y11@sl+utT6pZtO1No$yN2w38Vz|*VfIWCxA2g{nc?=UMN_)#>{pn+D>KOh_+N~<2DIYw;NKroz; zq8{VpW!xe{?Ky?@8J&<;<>-;R*@={%?|*dxHoLVBoL~1~C+O$?z+|Zoc?0 zbQnRHKfBZhDME*Hp`0~B2E#1v5o^&bvT^GS86u>CROMQQyC=*DlS9ELwzXOa5@ zPJ(+5c}%pdDqcn%hO^?`0?JzEypP_ER}p2o94N>@-}U9Z zwkT8Gk(anrvFHHV_7c#>UP7kl$Su537P_^#v)>f{pP0BE+9?>fEaa`M9Czxw;U7zGFOOG53goLzK*fkn2+I?{G z=8pz1+AVQWL(>e_f`iRgx>_boSOMnrCQ&b9_D6;mE%v%)**}-YA8RAY(Q34FW|;2@ zL@=NMx`d7nYjdM;g^d8oF(nQA^pOXDd-BXjN5?&jnL8jAt&9Z+GVyVmtDRB4rFD^$ z38=?^iO9*XS+sL9J2CFzq8FnIM;_;VK=+`7Jv=t7$)kvnF7A?8K&I^$9V z(gB*<8QaT(4pldPQs&k5CU^(LPgnzajPm@@Xk>l)y-tZ}YUc=TCR1&k(GW|oIpBh{ zKK=Hmm|;tfN#M{gT~zsEX~b4%NR#Dfy2Ln*vIzKiN`mS5R9d6^k$ep;&5v%93okwS z@d9q@le0=Sy+HxoR9<&3!+i<~>1zXdFCGUtbeKlr==g_+s#gO=?QKp^O1wa z;V=m~KZmXnM(>-_chqOOy!h!WY`%?V^K@8q?LiNhs%%>?Fu~Iw9Ecf%p0(s660^2& zBOEIt!m_l1K0~39ypVN*Qab%TF#cRrkk8dO%mSVXKtNsDqPxOjbgR_A6TXWg6~i5uRwSYS6`g@a{W)&D7vno?hhPN-M^ zCx+qDAmJAZ@~+>5d=^O0h`VuF9cBaZb7kXpmCJYZOH*yU&Gpe3o%4=Cbw86u)8z}z3x z)$Q&0S`(s(pQ7@Y4}=a}5g%|orG~D{w0-53+LaR;zp|>BXk+GJy#g=LsuIkH_^e{g z=51ffXW%U0w~DQ;tz!(B=ZVDIUKZYwHm{nJxtpe^#hNrE=FR#y{sw&f^YlzwPc{n2 z&^4un$(Tu7a3Lmp1CYZ;$YkNDJ`|D=Fw%ziJo~VR%H6&UpI^TZ z3Or`36McZk7Bl|303!%Imi77`%$JF*hCGgG(WX-o-7ota{Ldo_$mHtPyuU~km7bpx zH@$a;6B#RW%I*(3-V@HqSCLeoWPPkUnPoP*M4Z$L9hF;F|I`{8?M}UW3m+BX<$o}$ z<=swIgIeQ%FgZj7Z{7D86JzSYs2N{i`j`A?irk}Fk-MkGuvmBD;-YCJLxT|cuZWH} z)Dy&*5==&>ZtslLLvU>ND3xowz%8!P6YeOv16aLx(cD-@TG6JR)U?zXhR{oS8X#;X zSvuBrm-!%}D@#e?6ze^?kNXXlgFf|tt0a(NW94%9bA?w`qnMm~OqG%sbbZV5X&fEf z`)Omrhwzv3!o!O{kGucg@6~6h%SWGg#y>yPxpAy?2(+_&e|%0LjT$J7XP%x3L6BwP z&?O8J=wcz5x3oq&IeEu4@GU$Je9Ik{(rL09t`mxZSM9+6@YtSKY8N8rBALdyGk1Tm zw5_G)xM0ggTqO`TU(ot0E1cUzKtMEmTUzSkJTq7tP}EX}nC6l(zL1tl^YMGg0v;a4 zU7jTg@h@VfO?c{+c4oE=Nh?;v!s6m8=wU7kH5V8moLN3M=tlK?pLd$|1YLf!;4=>j z(@iw()F!q+N-3R1ohDZ+{*M5{0Gv?^!ntKJ9$b3TuKA|bTXiHtUHAf& z+MqEc$X>Zkp^fyeOLCXGSCmcGB&7EdH0eh|2tCAC_W+f?gaY?xEKxl@292lsgEmB_ zPg<-MronM2We|p`_u%*#mBWEfc;n$2OsiF~qN$RflVBfDsUNB8)T)jT#j3aIGvh)! zxWVHl+luN5gWVn1f)YkHzetG2fWVPo zqC((aum1+s{om8j8`@N1ck_|g12pl{#q0$0yDCuXnvlK6Z4Beb^xl_~CmTJbq!$ig z-k)vWi44DYV88{w?7?Uev4EzD!2Hb_?-)^_Ue;G$-aRkxoDwZ2c&gw%-u?w5uyPTb z)oWC@(Dg9Hl8PXsH0gV_F9+Wd-xGD9dm|mdTjBP1T*>=Cuk_v$jW_1=U3%2cWbXgF zVlf!@ucS@vv6L<7Ffj3WZFLfe>Z(!tgqycDbA};w-%A>BSwWQ7`%+g2*tg5MxJFXW z&I+F2JDp1Z3#C2x4~+HO9T>I|KLBWi9=v>uS)5w1v%D*~or*s$C-(QRU<~=TCm$wW zoT%|l~NgVw>x&y@XQ&D|55wfhlG5l`>>f&)9?mPKTGn<=;$ z+KtuwaPZ&;uuM>%M*am3X!i*(E<5)9`WnB1sU>OpHa(er|L(HElZK{nQrSs69Tyd` zvhsy^kE{ibhI1jce`8b3`-hZ>n6_8{I8*G2h=(N z-y9tEpcz`69`urv<>A`&z{) za8YandZL&mCnne~D04AOn6~#!so~0;A7LYw zse8I0XyLCp$>D(BB=aD_@g7?sd+~`AU3r6UNBTDL%{H(cmmy5-lj8-J$HZJH>DBDX zCm>!jn&W0IF~_&btG%0ne@Mi{X)5s3R$e)lj4cPlV#J|i{IB~HK84p< zg*%AId371?vJNdUqs|iQX)N-Dq7hC2i)A%y-L%y>KXoWGb6(U7~QH?Y} zj6^&mpY{XX%XUvUj!6q5`fJ_l3*z(CujnP2cHy{=s2tVzmpUu9RM>KKG za^Q636WS@_$?>y68xgHC$7CkU6v51DC26xKU=p+kIOxP0Zwu-vDXa*Kg9d#~yOt(I zZ%p}zH>1leCDs1vbang;s_f`B7{$#t86v!?oRd}~*ECKK#OYi~$^v@22~%0$(JgS8 zBqjB0a6iNPIXvP24c2s?^+%xLT_1DsVWm9CAmIRD(&nHN`jP?2($uyTgx-rTw)m9x ze1sQXz%o(L)$PdqaZg)G=A^rO>3m7qu}9pamr$-kvVfG~a6!HXJ1%SR6No&^17uR7 z9>kZ=s%pfH5#*P_Yd?M9e?}QBn1nk0TQl?{IZ>T-2@8ZdZ`C^6yoH=17l%G}zhsj& zISTgu*$e(TeD-n_))A0m5MF-QPK>h05wk*&;n`j@{ibCpD`N_Z`IcP6)qz(hu)S3D z```OGBL%Hy_yh)VbfJplHiwo54c4L25$dv}>024|X+GcLRBTo`W0fUiYlSvkonvg) z_YGKbLtfkisr0LH=uGduPT_`^L7g#Zp>#qjG7vfR`r-1i)>W+|`BR{8JJa>gz0K7$ zMfrFhUVP8Da7jo=W#xO?_zd2d8rD>ohda#IM@ZjYZFS;f462i{$P^aXq=9PBZB$3Z zE_rzSrvxQD?mWh*C2Qk2I^Ndkg_+BWTF0H5giBDC!51}m&r6|*O=xomf}9pNX@9F< z(KQGK3`$zOxZkvR7qG`aVC`u8hY1fXBLshkFQDMk^_~Df5NB?La+U zC;WfN`pT%NqIYivC8R?dh6YLL1_?nzQo2DxrMtVOTPXpN?(PQZknW*|?#_2}@BOcP z*LuJCVVpUfbN2K6YCn6XSzF|5mEj=42#=kY2|eO&Ce7oYp$0z>V6+35%Q1^!0*?Ho zt)@8i{ZazY*VzgKZDNLthKiW>?(Z~ebz84cl%`gQP!o*LjC;Y}pg4`3XS<$->atc* zUL7vFu7Td&c12RpGo=-H!Xc#)O+1S)=o6FDWUffTsn6#u&@Glo9Qe<(CAWhyE{k;; z(Xc^}CDn2GG*&84*i$Lm*z5~lpz93Qg5P>#*Ymf5U~BjGh9>!cw15ZILNQ@|5b{pa zf0lwA0WD4~i-8#z6#g?cJz_I#VrShQI=r+#F!(}uamE}>RLxiKt1EENR89QqB`{&J zV6g)s%-X9P5q_+gCvLWq*9A@%JmI8_0vBE)EYd9IXKn;v`9wZRx=o{7*a$oz{v^65 z=BDrUjY(3OI$CRM%Jo=zmpO7hpR4}+akB~u;wiJFd4u^V6OV)w? zWSw7lJ*+W|XGbC#Is^G_)I|CR`?V=w!=Gu#$wDlze}7+%&FtNryfTsHv;Opfy$mzS zYUb^X2gpd1lD5xj)qfRovRLrpqXKyyuvwtTC^4c*FKR6Xo$ogzc@$BAWZ~HMMuF(% zonofOq_mDdH={~YT5-7s7VEom8Z?9hZ~K9SsG_gV-NOM`F#s!xl*WI$o^REmEhH6g zT`aQKIOj}eo;YT3QgTgZb4f%(lM*6n0I%Q< zG&7I4#(G2MU#j@oTCWtHg<41w&ntYNWRcZ7yI{P4XWUlnk?;j)J$)*um8MP`!4;zxz6F{BSXccRg==+0rm($@L}S zZXd!@#K>BqXY=_O3&;NIr+Q1l>YwzP%ipoX)pG_Pi)({u2>f{>UC?(rH%sQKt+$o= z_;9~=XtWw;3l_hs9F6|r42{ArIJV*&FSIyJYklWB05et;4hyyJmf@q~>u?utbz6I< zTCKA`y-mYSC_C-u-PUN6`2r)gIH37o@_JTpt4U#1&ioz2$psT9!At{lnQ?9tllmr? z#cj0pIZ>Zg90DCkQ-VhG3oa_~k5j2+c3&0oaI)^vO>LtwcPkeB$5-1rR-aiE%DsLe zvv<<-{mSBzk0z9NJ$7_Ko2yp?5wyqK(w?m5{nb{MHNrJoR0a3V8|0`5yFJZIrkD^< zd4>(J;R9+c>z@HnZT-pbZXYk3o3*pbOFcLi58Lpfm}?mNQmt9-rZwIYLgJ(+H z(;0kzrPo%f|B6S7<3jF5Uu{_92kA|YR3dol!N^W(lU{2U(=PtmkvA)a$>!Yc-y_W0 z8?kOvc;Ein@yclR-QogaN2Fs4clqBe@vY6RANbPdncd>NqLQ$Xg0%SE`9xQR%~oxC zhuzdwq_TD;s%9-FvR*SR{&9AL(_8+P@#wLV3BFabf4j*pM5wa`R&eJ#sy=Y3l)DuZ zs20yYP+N8G)XNl{nYqYFGvR8On6H7Z!V^XMby;hzzzUZx12yL6ch>UKI8(oEU;dBUr;0J%cYMb1<;yODkXHJ_*ETFuJx^5yykab0hm@Mi53!aoS3X<_br_F zw+rDrwWle+@iGo2r&#IKs*tHX|K6P6zj2C4A)Cab5pUu*Tuyc(DLOjALJXxz(W-}` zZ`{H^=Y?zkg{S9l_t`6TX!6AN=UlT@>C4{s=dyMm^}Nk-b_wAyjD}|h$y#w`aGJ{A zTJMwpr4~o(F(}9YnlQ3Ex}jD6_SCuGcQvCoQvWp5;j={}XQGIVAg{U85b!#A%Fp{R z`o#pVY#C(sUR#jA5s0*C`Y4&EJnC}aPEKe}SxqRn58LQg<88K?gl3%fbI^5KtrQob zr?mHG8CgwrV@E!_oP4cg;c5Ca^N;irSs)yGUU*%YQ|q;@;+qiO$Z7mf*tx&j!<8{G zP{9ko{Gsp8#tjYkul^V49km9_P-W5FQcGrmy++G>O$>%G%V>T%AvohkP50M=HdRVd z3^kc)gI}j8g4ESMt4<}o*0QZib)Z^x&1+`t{o;6|Wa0zE0K-UvPWKtZ8Y1og*2z^h zOWQr7v91ecDYk?kcbXskejadAdx?^7K7#cgFe-o6?CsqFlZY~CoYbGrp-rbo>iKY+ zxmu`bq)le7`d`9{#ifMH}_1%d=6+q#zN?Ig@y_O+;de}k13qv z6utA`bcvG(%D!sf&SZY6lr+9oY-IHLV_hV{3;b~ore%I6{jd8+am(_*dHvm+hz6PB z@9uX@yZUUZTk@z8OtaC2og8jmo6fPny-xc5_s>c4eCOW4C3V65-814+Zkth;YA^BV zhkZEt*(WWl!WP9mCS2eTCd`doeKAJG z`2fIiu!H=6Z8!n-CJhK6B)|B1{-&wsXTP@n6`jRjOW^q9;_r{}2scaHNJ3VB;gbq9 zeoLpHF;NT(K_Hic_xT64AMe`_^-f$7k}66T%tMs{V&gE`OSvS=+AZKAN6+vkD$!(K z?`loJf5?p&D570-E;Mhz@CyV)BJSKPL|JZrJ-ewd4eq*(qRE7R+-nQq4 zB7+>{#YiM$Oh~h2v|x1eMoPlR->1}X`q}SKf7%9WZi4vI4M6LY5Y@!Fj3(36S$Y_X z)&808P1{L9kI&JC&dD za7ZBc-MU6(vU88=xUlDaap@{9=HcDetb%jPoyqH| z$9wfP$)p*e=Du^K4XM+y?T8j&p$}HecyN(A%LS1}pT9ux9mqbkY(1|(hp^;T|2PLa z+-AnZMG+Rg+(?629}eWeK28m!`wIg$Mhyx@dg=(zr^Lr7LiuTt18>MV5TI zsB&;g`0|-YRiGC`mRQdKY7Gk?8kFI%DmeflRnf3H`|nC-++R}!8XS$@TfXJ#q%Z%1 zdYvkzk)6(~YIMp%%YjL%l;tQO@Fg<1`FSSSr^UnD**q$`4W`A3o84Y@DkC$DM-q(I z%5z97*=0X-9IV)~U4gG!Cw=S0|D_{#xd_36Yc~09KZVm|3({{{eWq{GA-=sEXpy8p zgQfxDdARF04ZW8vhKf1${izv%XxW~>5${E>=BnI#$Mx|b%DX5DT<6#AR9FQ2Ruwbp zgM)VMw>8)77X8V=nm!_3Bd~_53)*#ae$KcI*D)p0k%QE4B03~BUut>rW;Mw!yP=Q# zR!!SUAOTIy^6+YMS=|^~zbxOjEYeaXO?iRiFKitT2iJs`ofr#FzGyLg?xgn~F?Vn< zZXJpogLmsk6=rZMqNCC1Vq7S(M~C3KL~oKZCcYP8DNHwe`e3Y8Z@g*lN^XF)TjzEa zV9}`QWsqoPmDc!YqnovWg*WR8Bo^O=lUhxbDv)lTBQB?D7YcWjc?@vnqKT(&jIhSB zEoYz}G%5ABRf7y$SF1U^X86N8z>jnzgX&8sbG&#mc7vm?D#4F)bW?&3svEEA;$!O;_weL&FvQ4viA}WOL;A}>%aGW zcQKL%qt#7Pii(&*$q@)dPb9Hk#Q4BFG!bn?P@>b*TjPp`j65$mHHemwCwT{O`2R{a z1RB_;&I+hNOXr~%AsK^5KB@KhXW)1^IUNJRJGx7zC8gzJ5wX?11L>zLdfAU5MNKLC z;ABifru`o+ps8`cDJDusD3P&VeReU_Q!Z?0!Dzx{j*3HiCG*WN+gi7ojN02RPSAbo z2_-GZN5&}D*ikBOHs#3PQ4cRa44&i2i`4yU7`t~Z%4fwfbEdms1G)DINsfXpZZjR) z5t2NE+AR#j?JS1inM~!v`ohwKCl}?*eK>@e)!);fvrlFq(SPfCBpYn z-wTW!A@Zq136`p>8z#Y7cJBdT;pLQXuGwO}z6>#Z%Sg1uCWgNVxUz z?!t;WU%EX;^LpQQU$UBI^ju`#L@%Zh@Ve!Ktsc3P9R>w7i{~PDPEj42`tgdT4#TIN z#WQoUDOPf|vy+g|GiSTbjtJru#lMwKI*((xJ(NG!CAGYZ9+{ImLjg?fGI_DN=KZkX zbJ$}Tjtq23`{Nucaku9sMswpK5t{l`I;EgR50?iagweaYVwJOb$8~D{&PLC>tb7Pj zB_qu=fG+A4G?9pX^NlEYAYH@9mYt?Fcd2?2PKp>iOZ|H z3CruYD$F7D!*i_}9e$wRCMZDLDjU~efM2z*jPi|O1m}LfPUOD2knyTx3Vy!(?dSRu z{@YEB6&9iLWohqYICfj(3l|GhC^kQ?bC%!O0Y&*(X@cvjnbVlGsA4YG=Xy}B0 zMPu%Zct|8bZ6}>r`6yt4up(&Qdnmp;x2K%^wY2hrLfG?izFChoJht!ii3|ANHiNfY z=WY;qbhss>=evDEv?2HMBNrs>L5HNxO9O3iXW=g`dU$%+r;g46(Z#$?OLs)itf{W< zj&C3m-qz}x_@-4{1EEvjl>!Ua_Fc@UdlF@9YX#1wIH{95X?3Y{MgF=)_;Gv_)=ZGK zdH%lQ+`e%!eMN$kT^-HrkcYTw_b zNnmz)<(Q?3=Lv<8fK!#XQUQPaby)F9(6!~6ae52|2Ccs#%(_^uu&ZDTz?j?DJ9Ogz z7qI?+jvWwvL4iR!2G;{_M-2a=>TvcJ*Uq(aoZy^Srh26Sc9((Flq-4kr@2$IT%n{- zU!d_O>?tqGm&Z;IwqD(vk4VE_#84_WrSZNi*D9XYu^&2ucILqQz;mLTjedjo#r#-L zPmr7Lwj+v28Xpr=ZnfATMdnI<+=B@5I8u@#O-M;`how26aK+Inv_ON1uTD@{n~ttw z8M607p>*lym9z1+TwGkso|kEy(YUW)e@x@&dhck(wlgScX)jf~T>-$hRS*`6BQuCq zjo7FMt7d%R;cfQq;nt6RUITCr`oi5;iPobjZEK;UHu%%cAz8ayadf_Qn8@SxT=h5g zVl7o&-Nm&FeXr|{(M)lX`!f}jp%UFj;j0yRCLNphm!qwm&sJWYyEQBSSZsE`e7Ebd z{x>E`-^;as8_YEPgsTnoy1LgHtd@#X^UOEE8u^XM9W9v5dD?Fdp`LwzrchI!Q!Y2n*H`x-;~S`%^nlG98`|by*F`&7 zy{`xO>^FZEEX>SY<%-;Y*_|rZxZbNA`IDP#3{^)BMUJAwit5Wr(sS#7le%@bAireG*npH5~fT`M~6r$vRhPHX4(~km5094q;c9ummzq$V2^yJuc;Y&7#Wx& zo0L^Xz+;uFR@i+mp2Ie6z0^cla&$y;bp_bSu*9jcd!J|B0dO!A7lF=aGXJ0Utp^Rh(u)p;4-pUO2 zI*H4;@@TnS_HM1LjI*{M5xQKdz@nmm^9GEY<50p-mx=T9^ZUVJcCwKs;G7j!ZoAgA z{BTiQyX=r1#~5)4b*W{{9h4|G+>L-zEV);WFEjt(La7 ziY%;-OT@}NRL`38?><~{npd2tfbl1UhmL~XDk5`Y6t%dTxa*_5Jj6Ws!4+sQ#EW;o z>YqV1I|qk)kp`RP9A^ueqeV-Z$w1=!?|A1fsr)^BuvCAO^9xH$OS4p4gmf1d#OPUT zuhSF?@t}8FW&3xy?ms4q(y%_$Pw5%iZ)TFa9Czd6v#*qqcwIrmhAG4}v|7ULVBn4M zm#MX!52_fn;MRAVHOcd&4-Ts*+n{3L^1hv4w)v-s+YzpiAxz32<(yhjP|%KLE%gH3 zI}?__fnLi~=b$nlZ-=NhRqJ-|i@CF}8ew&H#9diZ;4AjcA0fccunGkQMX5M2m=81m z#p4}JB#MwjlJDf%#v9#wyPO*!B&B!xx%!kUnJM3cSA2DH1R9k0p3GXvD4;9^lh3=+ zbciUP3b`gY4MM_y>9VnmOu^%_33v&N_jB$d72>qG{WPa~{7l83WETwDY+Yn0(?t#~ zC@k^Y_HT{ozpkFva|e%E(xNP>?@`GtXd~b|I;s2*_KlLpgV>uFOur+2PmqKKNuop0 z6b;o{1Mj=^L+Wdp?T=()HKUxKFZ`&esQ8$|4Q0l=k~2H50V4*^SGMTZQ2u^gH0Kr% zN24KRfYJYQ-Q}5RvHN!Wla$mg&D2Su5(<48j&OZ^?=_Q{8s*k;|6S0ShR&Wn!6Q?g7Y2%2Khyd^U;Gq98| z-%it|yHM(2o2*&4-e0sMLO!(+twI-krKnL6p&UsR4!I=)D^ztHHkeB;YiK4kO(_}o zduAFTwPfUpwx>fp_9JjHf}9X?^CScJkG8huH{Z`c!j$7X5?Zg26UaZalW@?`84ZD5 zeRHIw2+dAYTd2G+4gaHgKS$=gAE#)vQF6h7k4~y_4X1KOA7J_LU2XS+$*K-j80}6p zd=m_`b)BT7q({w{>@S|3qEC|s%Xr}v*ndihvpzm}4F+W`(z$w|ad)FDTYp$emu;SQ zH8R+@{ghOD*vbz?DH6pkXc+aV>!4KPw88|$5Y2l4KfYGkdn6l4mIdp@nCyQMi2rW& zeD56PU9&^rU;Sr#%Ks6wwyNj6ERU#^gOPD)&*}^J-o5p>Is&UZZ<-*YXZdcE=k@E? z<1JZH{E#h!>h8ROD&kljYmVKZP0bVb@IKkgXxkqzHEBaJBm4XN-4E(>%gQhZq(~hn zlG%*oqa>rqJon0bWp44(!{3IQZ<8DxpJzV$# z9C`@N=pktyCw;fdS|sUPo1keam!|SqFEt*v+(vodiO;E@mFpJQ>YBt+13&C)mn%Vh z4~#Sf>D_%iAqTzKZ%ax%Q_c0Zh5rbrBsdm9m*2_y+;qItc$Lpa z%Un-QEk>liUsxpClE+I{S68E<*pZr%Qqa&>ci*!sBSewd)~^%K+G^5eZe zJ7rR`OcJa9l5vk}axY_PlilsbKD`8J6v6hxe29MSZhw)#IUO!Va9AzWVGT6Z`SMbT z?VZPE+`Z_zyT4pk5AxQtAL7!0?-ROSkHevp7d-h(HA&a79xFRHKR-EZYSnx`B|v~p z>{VLSON7gEx#+yiv+QBtflNmpAH8w~&OK4k_qr8_900s;b=+8*LGugOY4DvgJ-F`^UNHu)|>BTCn8*Xo=wTW`u$I@0wF)7>#{ zeitQib3a=J$6djDBY3T?3;O0`4 z9LA;dUUm(@BPzaIAqU56(#Hy4uj8CcX^42;x$vUwBpgAn#R4G1h+)|p`6VU7t07dT zgUL@Q+NC!`(A946&gM=fHO3t+nAB;eNV8JUFL>SVmzB6| zX37QJBq+@YvgYs~i^F+=*EUp*crKZAOQj4(G+w}+ceM6q z)(b`bkR0jrVf94=@TGn_U_YUz*7xsW@3zALY?U&Jb;ioZmEL;dS0?1N6Y49edXb-- zu3Q>W{stVovD9$@72Ozsuq%$XMQ0rxfmcMFTfk|rO$uMvL8<98HkRuOwP^-4wG)pr z8N=`ib~F_*mG3$5nzD1DBcXBaUq*MjiKc4fh?v#w!`5hv$m!KD_5z7M5M{7Z=9Lf8=7+@rBPw|#jn zel%ZBwhz^)&rbKV@elGE#6YxN^$kBtRhkZD4C}Xi|Gpc*Ct^K;XpK>nbmrQ}LiN%_ z4FvPMK*L^+a0X6PT0yg|;@%6V7e@~O$gGva)IQ~p$S1#jp6dk-#0L{OMr|N<3pP%U z#%hCWm)s($@p4V1ED}WiNpf{mGFX9?9l=sD;jJ1`-!}Nza+(b;X5>r=(bklCtv@vZ zub}p0;Rg|irajwC-{P8CDlGpOU6as|j(2aap%WQdLxdE^02OM;P>PU*h1T1{BwZq( zs*kPQCzX2b?*_t`eYPdt-|?yPoGxa~#NX1R*I3TemgCV}otpc4Z~ic|$x|&CT^9e%$T_e+$*9axjDrtv>UTdU{FaVW9FZF2GhJq`gI5&Lu}TkBdY;>vpIIKVU!JZ2i}vuu>Gd5_S-r!= z&2mQac|W)nK-CGKq>&#m*RSim*i9$0*4EgLQ1^H17Sq;a!@T(~#f_R6OQ;}pJ^?yiPwA`P*{U!9 z;@_xHCoUfQB9g7l_YPcg8g+#T95!(RC*1G-$Su?pGjP#hDdpXkag1Z8$Gf-7uW1Pr^ZgG zPhPs~<`2LKJH0orlPQcp5Sd_>;OHHff&psjEJRM|VS!vhcZtl}PJbza>0RHfZp1af z(%lVkmF&UTo=bWDZR%7wMnGUPo%DKq!EL$;=NMj5J#)GK?Iv4c%WGAeP&bkpFrcc&-H@?2kUmq%X*#`iTZFnd))xRex z6x34Z*dN&CsT>{cDPhYZ{Q4cZnlxa)e8jbIeaOZNu{9WPbVmTe7pgY&)D#1r=&_f}*8JDbUm}f1WRibMW_hXZX zax*vrK4JZBp5q!~o8!@8TeI^6R$@6>hLJC0M)2%4X*+kFu&|c~WeEKZn>8*SWvPmv zpduTP-I=a}WmmI5zIyelZj+dZXab$10}QT14*7AIUr_K0a!g&k69LTvic>q%t0Mw| z1NeiUL$6DLg~b25uM0PPR%`_j`aVTlzsgM9PnaB8_%^ZzJ;(U$J+BSm7s#0mI9jNL zS1&SjoGHoflX)0u|NHOk_9bOuWE4L`A9bND%73bT1c0zX_5=zU(FqseO1x z>Mi_h^y-valoJJ=nfmv7#Hy&>FlcsR(Y&RvX@`k()*V;#PWdy%ya2&oBNxQLEkO1V z68uUJVerGnqFqsSaKYon?ZUv4862cc?fHgtRArc0Kj!!M@g%90ex7mq4!q#diMP`l z!uMzYpi)P_LysN}Gp^6q7^!%BNnPrY>A74IiRno`Vl=U#B%K{~Vt4}pr6KvtYy7t~ zcFH#D2B}9hs77Rd-ax#YaDIl)WfXlpm0d)gb}91vRImKfH5(g;72}h`68-zyvJ8(C zxbur61*|ryGvVv+p+CUpRNv6#>vZxDp&R8YrE<{<46b?0jO7_hI}L0Qqk!Pw&G5m2 z7$o+d4tBig3_W9vhQ#jkeBk(5J>>KEn3*<_$_slRQ!5bDdW&>>_fQKRd^S9FJFUA* zGdfp(%^Z}Av&Y>0vMlO-Hcw6yGfYKYQ1^3eaWVTnnO;-^FeZfGe~M~8IA+E)dH)sx zMdabixM>`hGFUqV`)8xQO>k?3&@`;;j?Ev}Q!=@b$Qs@J=FJuR>EjfRhmkbeR4FypQuuwHHC?cR6Et6L)NA|z%FlJOM@|jdE z4W`)l#~KD>Wo@TQbm!-ViJM*$*t!c#%G{6X4f9E3vR!X0co(E&>0-~PPftxH#>WGB zE`_dHX)60b$m{M3=#*_3Qa;Rm*%U58@9u%D{QF=jpq7`N=?**?MVQnNcB3w&cqHt? zFyrS~jd%!fFY<)xn}soh#hahq9+V>UORUDL$n)*wWj`&{eEn;n9zKAw*K|58@E;Mn z|A~ef;mXLN1IYe~Affh&jtPJJAys)i3&s_j-R_pQs;Pw)*>}wY#)2rZX3&;E>lvC; z{gcO9FRB^on)>8bUS9TiWb-fkZj4@A$_ug2EJhRYU6QQr$%WsE$(G{smcMx{x$PDs zlDUxIpiBAtd}mjzf+(S*bheoZH?R1ixKJ!nfh8vF)cdc4SRYhgj<}ta(_E>^48X#@rmfP!Y8ym-0WhjSP!CQS@uk->ob>U$q3aoOWl}Y z3Wp>|X=Xj_cRl3jpLE(l5C-G{^kXsVJmR&!9vKNCLv!GED6ncE-^Uj0Oo72AKH;?r-B@=>Cw?PCy%;% zygy)rKlbkq?K9jr7wkdr76cR<$?j;SeXTdDHe-}J*QXWy<<3BB+^qU1kJ5pOvD%AM zHGvBr?}`GDe96PNPdxA|yWwmzdLiDadC|?^ZO7i@8x}AyFk~G%l<9Bla1tj%4gj#D z@DhDogHsorD66tbgjk)d_svc?_0c35;Co#*E{~mS3L`i4XGiky^fQ+J-t9?vZ_J{Q zo!|{xK@7caUV;cvQ`qQRAI?j$UVqJZj$(OSkb-zR+@DWZE_b2}6fG5#p=F-3GBQ$m z5C^akQAgEwI}D`aeV0G1&XYb|ZQAo@drlyQq-NF7p` zB;2Rq)o9L5#3n+blx&{Pom7cA8%4y`Ke>0(U^ckh`UhU2qA}QU9JhsPW%QV!FWCRG9eM2S3oX!Tf!^EQNk;J3=|i^ z`nv+vLZ*M>n42z6J(Q6FclLaS|K_%vEz<={T!2~-!?RltCmw`aE+xXmc||I7y?@>| z(-Z6dT{1WSv=eLURfiHwr#hV1d7?M?Lk?4W~1&fa*KCWV`?YcrGNbE`2Ed{{<4VZoJ~IoAV76# z0v4Cw%}Hl>yA3`RtN)c)?)1V6`KG;(D8YsJ7sMbY&5EuFyX$}5N0G=BEuIJUu<-z- zpeH%2YlP`B^?NPH9uH%s6jJs#FBzA*0rCu=>n8>|pz|)UhHU6@N4>S87cu-zh$3w& zE81lGBcb>Gu0FGfj;>5dz@3e)EA6V9B&!iPIDEfAmC--3YilgK@`pEB0Dj~LWHQ`W z5CJD97m+^h|7ZatN<)=d-UgpvU$Uf~bZ$tfz=GFa+24+SPNaBtz|=Uf^g3!lWct|= z9MW*k*}IA5M(4xu>-7q$(-9HrnN$K=JPK$cM_6Y{7IR`!QsX7;ZQ26C0iGxBWsp9h z?T@rggR*pP&9we6%ErT&U-iF2FQj)6yUl~ z95^%EfWJ7#@#>HWJ7A5CY)P5Jv*Tjk8WNDHRD}8!^48#4Be#8Lwl0}3Lt*L+`&E&B zinqMf&SnN8R3Mx_PR}p!^FRbHvMDvpCEG5`A$&4dKJBZxvzx_EuYX=q(P#TxJv0nE z%l=n*?X#x*PJH`D11puop*+}dfHPUnsOKZ0WXkbG*F-7IR@|!n{^-^%YldrJXn0}5 z_E{3~&9-m$4`#)Og?js4&o!A4Nzv004u2g&cd1@obFw(!4y?CpUx`)GiMhicT*1OV zgZ{Dic;O&yHcax_!hS*rZOo*g1M9;NY&r>?vBW97B=Q_3<UIog9dF`T8Wxz+E zHdf~R>HiBfS-xKKyKwx*CBtCSwqXM4jK;+z?Bqv0}U1Utmo_bzB3{I7{UbGPCFB!h&d4NyYhtGj>-{XaQ=`;GoYO= zaBkqU-bd|-7ozE)1}5#6$_p)wZhN08i%%&;%SmfsKs~fFsa1T&KP-A8)2uw*X}si2NpTDOL^0 zgp_N*OjHtC`zjE=ThfRw(DCcpEW}|{6c-SwPOLUpQD`#!+(-!UL#>k{*-$FH_p7H* z#Qol4cX>@_d^hbpksO<)B*W!(+SAaEQnYM8k(|`V=-$%WCZG%Y75yZX979}Id>#CO z?1yFaXZzm<<(Gzg&x_e$;k_`%k~Vq+3FSXO(Z~dov&Gg~SOW(z0u5&FfHW<%SJnx7 zweL#`mscNHQr092lM!T{JKxQ{MA_~+zB>f=fp_rAiU(-H)v3j~8D4If@|oIoHqZx9 z+HVgU*Al%C-Iv8XNyr$t*Poc?mL4z&HcfMl)Jht57%mF0VOg{0T}?`Vv87iY*M=y? zR&9Wv{^sP}{sC7PjclTZ@WsJm~ zjl;;l-zgGGwd}#QK3ndBLsU{0&N8siVaosJAY>a%70K%tN&1+o%j@2?k#zz%O3FLm z`tTOjK6-LbvO<_^Hi70oK-9be2Pj>Q2MynBZP_l96FP%2qULP|li6_F?u-||AeypX z#|^p4?;=drY2Qgp%VOgOunxj0kzDLzla28i=;Zy2wL>rrerJh{I7(z*)TA`wLxxnZ zgsq>pt1vxu^Ta@fo-!Ib`=E>@J@3%AZtivyGdY`i!tXTOV$8M;g%L{647o{O7$JtQ z`*+>qWmd&nno${dv*NTIwl|FHuq+I?(>_aHIX(Ega469kRFF5ub9qwp~XlcsP z0V*(IT=1HUm^F})msX=Rz%&1O0p&#HR!>OSOQZEGH;7u0tr}9@XsL)^Rjm<2(kHcP zdmhk>^mnW`YutQ}s${0lcI_%*hJ9Sdr4s3*T{dC0ax6W5ZBUsLQ0XXm4&c04(*-Z! zVmPYMJCNTmz^!^{Ao6>3ya1JVxtQU5C)R<{2FME#GKc_!L@gb94D_HOq8l?HSRuI^ zcPZdTH?N7-m0FFB^9nFUzW@77{1ia@A!Ur2TFP{nRpi?*7kjgx{B+km`0R?{bE9s3 zPU?9{knsX8EP8tsNU)U<(&11^ct@My@q>*|aa(=v-5!=0)q`0`O(^-q>bPm8QWxOy z_d@;keqyZw{cTS{3p+7kzQ;rqCLxm_5yHZZ%w}KAj87M9+OETOK;oQc#7Wza2u)%u zW54@~%&^7J`LenEL=yU$!ZbemB$RPolz4?K=aW$o@9p%L*i-Rxd?Jtj5_>fM(I2@Y zblL5S7(ui-+$E?YCfA!8E#Bz?IgxJ{x=zSRu4ZMjx?EnlI6JHnpr<_BrS!OXqgs?- z8I=4CCd9=nRcgkmwnTqmck_W4snouw*KUs`*Lf5Cf=N?Ky(AvTW^k7Gu*UpcG`Rrh zqhP2x#ygs=)ZlW54l5(qo4Zr;L4fN(d=qK&LYbq$CGeRsMn3bx zN?Dsb{t!nr%E3TmB%x}h6Oke5fF?eWQDWZ~iCNM~Kf0en)k{Uf1v^-S33|J98-be&TKG>EByF7A=v!#4jR` z(Qh?RO9q*zlGu%nk6um&96`2qkRD@(1I@Qnfzxy_07Db!$4_so90yz%L)v1PDjcks z^HFgOG%akwWuc21<0p;QfWth(mA1}CP)5!x!49w*{T2^bw;4e?5H+aWT*{Ua- zcV{Ah*4pn20sH5_pr{gaf=SQ7E`CDiZ!(?ClRZ zhz#GEL^U%EbgcKqnGGh7m5qp0YY|054nTJ2_BhIWFvyD1nZ15#HGG3O6~f{UEZTer zfe!iXxb?U(=NRMG?+YNm1sqZ!g*y$W@~Nt-it@s$s;c7Uy{3vZzfBc=S#G%p@G?Ij z;qG=jH)GtfveXwI5l9dc0$Je-a{$-02fa~=(Izft5YfThbeA20cb-&Lw{792I-7?8 zB>?EieU8bTUz9QVxoV(*(AadpR-a)%}%U=gwTwgy`)-at?d(_hMAdm>YXsOx(s42L@HhU4b?C}qQU3O{+J zdzWd>OVVVyTaACqZSV=P4ABP#7#JC|6Gq|7if?Tgz-fO{3za~dO6l!rMG=oZoiupK z+oX2Tr|ne-GJ63v!_|%uf_Hg|RzoM9Y&+5=y(gWSuNtiQEpO~)8COp_n=j_R;l5+| z@bjESgamILnC)xeMM#Q;3`?Y^Ln7Th0S!}0CgVcF;kI=FAEEv}bkZgSqEnm$Pv}Ae z5C45`^^?L;7eP|Mho2Z5z}PwYp`4VH`@-ayYTmk833W&|qPxcKfD!~GQU!<{z3Vpc z3JYbc@i(!d>hsimL1v|mYltGx7@Fvyp+e0)su1o_jNCimeekfH%*Y(s3`vXChOZ6yB9sbNutdyedqDg_2_N* zx9*5{x_Ob$Yi=Fyu8tihE;hFnf4|UatB-D`raS8 zAFEl%gkVV#XQZ|y6pr$9$kl`@jDv zR)Pr@gtk~mW0CEk6TCG5XrMC)?R(3eB5QYdcVFo;ugjnzMsT1x2s{dMP)UZbgs$yO z7B)I;SNxL~c&X{{w#!9{pfIr`gh~+(Fw)r2>6d5eusG=WuN|-Zn_}I@DLvU4$7x*w z$DN5xaYV1x1xsZ&ejpTFgFGcZlLi=Vt@i0tSE~-%P9`^ZQC?md4`p6(tUm(U&P;i> zXLtlxPEO8~H=-Ru!e_V9pAi3h`H$S=!+rh4MI`5|!@250PY5ffcEA&$RcG-eGwgS} zJ$X~IaJKz#p9Nyug(Y&ot&jooF9wx>j9h1cbupmVIz&da|5{y#4e-7*4++gxd+#Ms zh}!)TS+#45nwl1d%#uaCy?`yFsyf-^dWu~_^b#R>rD{G&b$bbGry~$$x>Wzr?Fs}% z(wB(seQL7plcR-1nDtv0!cp9F)1P3q^yR^#|Ixh@Zi(C>vLLAD;2O+EUCs^`=Qj(x zi+lH;SkdGC@?$gb?eA6)MXm<)AB=eTtvV4#MX3MAfaFDR5dLLEnFVM+gK{a{wD+UF z|Iq?0`(kPGoRf5&2!%adFn35A+cqAyvZJ=;k$t?h zI{c&@e&Atjr9SHMT>lX$>$iKA z3ewVjj}M2B2r0gs8D>7j;Xbec@&To6NdV!^tc>cL$G^Mndw#j)`HAc^WJ_4blV~{} z^!|eo60E9s$kHN>6KnwC-TLJ(&kKEFg{OW6)~iEb3QO~ua;lz{Xjo&qtPAiIA;(!26Upo6&?}&4jia=1=O3Bqkr<| z?_Cz(yrDNI<5_Z{O5X(Ok?-VKB;t|%sWMcVUXeDyAVK}GEvDynZ4yLX6Wa1U^?3k4 zU@Iwce=9si(L9az_UC(wdhy>4A}xj4a@5__@C9x!)$?p38Ng|DTCR9WFh`#B?E!_g zuJD?9y#h9j7$I|I*hxY%6o1l|5a1&Aio9 zBLZn#x}U(Sz5 zZd(+Rkno3|C%k>jY!G%BkLump@#XS+ky`>Wdui5{?67A_Qi*w>Z4}OM2Wx^RL5(TfoMmAAi zJizah6JpwG9;mTIuR|vmn`~@RSnTYXv=LEIOJ+eI!=c4-;|jR;Q*dOys{#~0BKTwA zQvPID`6E{kcw>>rf?Jm{vIvLWlP)T;MGf&hQ(8c53hMHIMQl6(^dH5?tMxv z=AJa|sHCKg>E~N?HZ&FatzhL$g#Wb^5(?YM$o4;eymtM6?R|ArlWRROD4O2|+Y;39z>|VNAT-Co(YkVQJQ~_ZxF%J0 z)AxyA7^Zm85^kOghHjlnrawmM!MwYZK!V=!H2sW$Bf$Ej{!B#z@ys4&6bTiA&-li$ zD>)tS0#Gh17c*<+Mx7jO*T-xnPk)%aaRR1hLud}7aP{Z&^>5fh%OAWId3wGM2m>Zn zRj7A3A1dzSj=R|s2a~Ikf@HwHq#Onl8~l2~vT;w8W^MIg3C@3b7KfY^*>|LmE~O9H z3^5KYfd+?2RVRCN1%1D>-z1oS-#oLwx#ziw-}~Z?8hC9a7G}7UQ93yDFs_HkM?U1n z(kAUWAJurSntrn7?|psL8#b^y+7(4WQNQH6oz%*jA9s3*uID`Z*~a-gl1R9m=9DHu zrQk?aA~pRUYeHVpabAqEoY6cJPzgvUt;?*q0cN>vx2kIm>{28Q>#^Q^2%Yqn?8H{; z4*TFX{==7jiVPWo5`fUQ`sF~}5x~dE&zqLa>MMPs#+&Q)y@Tmge|>OCu0W5Gq7lq| z#y`&SsB;MYuFe@cqz=tD2UCgGX;66`mtSPI1G-dQLWIYHfqa%YVaBA*|Hd;?*0NV3 zHM}EiM4*50J?$U4e_r)J-zFQp4KH{A8N9DpC;ZwGE%Fy>Oz)Pia4#6W$1V*{Upd;3 zWJ@s%tl?6g<-Bkm_yS$wTeFs*O-xLz-=C1jQF*s{LT~t7{-(-ecvD5%K8YH8P1-2B z{n{mIhQi?v*zFxTUQCthSEZ&hrv=yhI!A+L#}=%5V6k$&RJmU^!J-}`acQ~V1g+KP zygyGIiT_doXGTWd-R;%=`P8=)#z*b5TLEYj&Q5tn38^RA|Ndi!V1S4?50$+BC`!nO ze^wBj`vQWk*`*RM3fz5F!>9_5e}THP_I(6Q=b04`-kJHX&^1yGfxE)_SIh5q0~+TB zfEn?Nv;rs8-Iju6 zPE%*#4cJAGJ1{w?85=g^Bc9{5A%+}!B1!Rs#+UD1h%~W)(A%#Z;K-$lK5T$zHh~2U z!qm>226m9ZqV|URb>4fAETH>7tEBO8GOT$Iu-;!lkBpAdVSkC+E`o&#Ub&Z^&zVA~ z_3?duSR$P)m=xws>z17%B_k6-_20ZyDOfb=n_oqy5R`cIb|kM6;-p-mZACbPf-f8PraT>K;|KxLcfaY&||B9V!90QQR-N`s3Pij zi#`~VJmdYvWXWUF6X|o%LTq)Py7|}F;?Sm+c`=~K+0ymW6If9DNRoKBdVnK!tLTnW zdP)iBP4IP>8x4o3%_Li+YdZ02O(f~gapMO3KA02q@!r_@r_OtIvhYz%4!F98z={Od(h&EkZmLGJw;&oE~fH{pTAbYZsQv%XG<y`~-}EX;CHkw7yAc?HzM52@388ST8S^iV?iKrMV7sZ?! zi?V^owDvHX9gP|~F8SW6n@}*skpwI*X7~eCGB@>4Ei%0d+-BVkNT;ei#G=6&oBWu< z@j(TSKSsyInv}CdYBqNd{G3r|ByO3?(YEhvhN)#T(8Hr8l-FWW1w)SB;f4gDAu2KH z=m2oujlK%6iJr{%<$1x&z#%s!OK-#sHf*@JkH85DT9+EY?g0*0foEk z!yi=%x9luN@`I>PIe13x;fs!c-JlJ@Wc+TGDRDOC! zjUEqe!Ga*#c+Y1z9e@8a+H|%^LU0?U7t>K8D^Q&6x9Hf3rH%E;7i&sbbXkjx8*?7{ zO1|q7mvvnw$dvk}rPXkh*N1jmhGw`1CyC-J^XSQ{nsYyxG4SfXaD0YZg!s-@Te<4g zs{u0Jpc-|1epDN=vYM@n3C-8Yw2^42KQ>$v?!WylzboDEQu(OELu?z>??7I|qWSCX z0w3dS7Vm+UsR)!mh52e92I_5Rc=~CaBhe_O4;EW=`t}MRK-I~cO22)}=3 zQ9-GFkuJvL&dRbhX7#|e^HygV`{3rF zzJLd*T*QyImKe>$ zbkyUj+&N#CbDl>We3%>77Ke2$zs2oN-0V*J>Yp*Lww?XQF1Fw>U5!SN|DumVtilO( zj%7)%=h7E0y7cPh&p}?CS~3t<6LreWHKf!wS!#MBO&$7GNc;}?EjAx^Xu#xXX6pcw z<3{tnpTY z&8A8(Z~(rJs2N5V6uGbmhJ_`GN0Mn$@A>>J1H%TGHfT!oyx4Mr?-e-PjeCwLCfN3K zGw?MTfo(Ng*JNuL$|o6f;hUI*ab^j3VD-2F6_-m0MoC>uX)85bGxlU4fL%hG!3 zbeaECiu0Ox>b<$>l{A+TJmO7-h|ffB0893-+;|!rn8*$r_6689yN06*iY?V9vOpi9 z>al!cLc+4`+?AqYGRHlgq<^>(gs+?;dWI7k%j{>?K)avjj1dHgi_>_hD8FvA1Fz)6H3vj&xP#q`cWm)|yM&v{JXJ)MAv0~8}u}!{Doe+gYK_gML4ZEQ;FA4Bw zCm11tG~8JU8=gH)I)LyLFb2nqi3m4YkhRozMC9gt2+)=c+TOc;9LhGmb&g7CVk1$gL`c%_`5Nm(nB8YdQ~=p7u@y z`6nybnZCLV&fEjWXPfaNYmvO=O6Reh9I+)a;4Z{k5|$Yv_l&YROmg^Xsq?%~kgM@) z_@cH~?ufwt4$zG)PGy$;Ccdejv)Dj11y%3><7)&HR{dbvS_n21hr6 zIX<3nxwZ)@ZZe8@4Ft_nTbj=(Uf5&v!)Yae=r>vsVCdJ8t`!JiUq z-1r3R?>in#`AV>K_(Q0#;)sD57IyzNQq9iNf1D-Zp)$Ty+2(AKzq2ci#yl_s5tL5*dJQfqMap+wU=7`(5IcH94WbpT!l&yUOr>JP0x?O% zEv7X(>-)d78FM=VQ_6_#xP|mC-zD@}J?*IB7G7Pasy9@jIE7PO|09sa&4u*I!ogfY zRZ|fuY$&cTUXr8-%jkS=lDZh^?+-j9=kDUGg(ShM5-3}JIu1+v*t&w?>cwaZOR<_^ zLBdNDwfiuTsfON^`_A-ELN zPU>$d(mZaxI$HzwmvfrT$ZhqWk_^_CbfM;+TgHW*TK$o__|QA(QtccyjP=)RBr@*T z?aT%9Puy0 zZc|aHQk}0Bv_Grn=Lfq)#}QVAHjdKbBP03UL2OB91uoViXU3U1cLZ(Qu&%&9eg1O` zpXGdK3MUz-H%ObqKv1uOU7T0HQ5>ZP2Wld^w&MCr$i(xZA}R@Q6}dt8>aqGWYOIOeJF*;uixw-M z_HRke7RGlrNnuN@_jE`Lzat>eh4xxO1OWOxmla`3QFk#giq1cd(PIK2yVlz?9AG-1 z*<--a0_?kBIpG2fb0W(hkUguds1@zpJvl^;Iv!CSwO$_&WcgoOmCJpB$zd{FT{|)( z0H?UV66{B8*&R*@jMSMvw5MPdg8%%8oCT0wHi{!qm!in{F?c6HwC29G0Qf1~S?nD} zws++s}Jf5?B8bKO!=TmWEx`2&DEk@;ZPmt9FJh@@! ze3_h_+~})=?djy&K-Ac*8@FWsPFiq$fWazHr}B>~{j^ZE}!ir$G#p;+6x%WiQ zoL<~>pTM?Shfa`Wfz65fKBQ_n?GO&gBo%nqsPPBKci*@QeVv8y+z>0%Qc$J!?s%nC zf=^uUUI2C1=J4-u=o3RnymhX#(B?(BP|4P$U7>BB<6RdoDQ->}YLZQ~|_PK#gR;MJKiMP%NpS zM}Gp##ooOglnL13ffldx5d`~HGtKYA$tMS3Ug)$-1FRU(o$7CTHnKW>*Wz7zslC?m zer)jBWp-8CFhC3nOrFJ8M90 z2o9__2*8LKF$(1YXuPtW=bgtgKEQLnqRDs}?^85Eq;~rx4gKmCag8{MO;zH>?wF^6 z@Ry3Jz2O2kje2Jrq1g~E5aK7 zkq~9|bFxFL!i-HiY``mEUPpJ%{2k^V+rNTCcohHk5t`B(%~_2X==7kiE4|v~z`U4- zNUVp;SoX1g!;gPuH_s}Fh^*!DKDFG>QS#}UUv~X!_k=wu1=_`fngUH0qdLiy2RS|0 zLa7ue3Q}I4uOd_0`zY-B5cG!4j}Zfs79;1jNPdko#%ybzE|snq_eT@B#|OVW`-U^C z=9=jRaQeeGx5Z@y9E}iZ7=2|CU-YYq6aIjmbF_ZH;rRUTZypv|pP0zH-qj9J2DP`* z>>8#0EsA3gzyHom=}8p$Bq`jN__ER;N0Yz)3wzrUb+&pu+%5I@=S7y0aLGf-hnyjn z6yh!|N_6?Nkdr5liH4pqk7`g!T{pTPP8AW`` z^Sz^JOH)+>J8|sbDOM~4WBieDsShsWWiG1xYuoM@5%0gZvzpdNHqdO9r{v~& zHa*_r<54VuE!O=Rv%G}7&4^`CzFPNl(R)Db1|`(9dA@=4Y?VFgBXM2=@SP2y@zFl& zR2T`W@%65Rt*b3s#k)tOLH?q;#-0>GUa_S5k5^2)K*$T<<8nCQmN%5o@AA~LIRiV8 zvE8YWf4(2s`OuEWdoJ)}^$_)avCOI2^gR(m?{WJxC1w)8Qk&1ikkO)34{2$=pM>tj zvlm--I@AM1!labu3JMb*f7NT}H~r|uKshKyTmK+ETJ$N{>WFr*)Z*r5Xe9Gf{P2fM z`aDN%%hxlF8+rP1rT|4y85-LGY=p13p#C^zv>QZB>mLU^gPaiX)ojuylp+by&(?C2 zYH4*Oa{48*(l@huq3K{76;NpA2}dN{CJaQWg#kx zR?6KpOGO#5_nMDYCgPFJZ%1Eb2(GC+(F(*5%Y2%YMPA!W>0E~oOMgz1LB2X+yh*6U z&2j3Jf}dX!Q;Dwm&>RS7GkYeuSDSgWg;s%Ie9ILn3!0h@ZC(%7lJ}cyS1T4 zxPNg4&N$gniqcoDGJ^}6X~xx}^K#cIeUA-Kp^gfZ-c|oOMO#v-xtCmR}D(w4}lXZensU}8hupuS@8Jl z*RO3m#4||ZeqH2$q)G2U_iO-)F~=E(zF)7>qoJT7#f^psr~^ZSKhb+tRzARopvg+n zk6~zMvs1C7cHzY1!a?5knm~|7?}!ipF>|0%`Y4Lx*^ULyJe&kQNc>kmWl&yDezdAjr+ah6ZQh9E4S~0zt|qp|%X-Gfv9Hn&m3{l2upnomNi^(duVCxx~MrbDt_BRx4elqM*z1@`Nncn?j7 zt&y*?A_YoNb1Ec`r=1iC;IIBd;NU=z#=Y1oyd<~3)F!!zVeM*z%O2?4a}B8givH;D zTy0qx*%j)8*`80!r6y;Gh`m=$J7ai~fix6uqNu))!nd1#84m#M11t0bW$hCX{07`t zCaZE!hnXHP!ICU6&G{eFrjYovMJQ?xfF~-c^ zW~SrS3Yz|OyD)oq7U0{u(YF~Ecq|{r9(MW95NN!%H|juJFsK{GVd^Vb;EwMgi2j8bH}J*@!X0{DykyT= z^mt{b6wFp)+ci_ocJgUTvURC?3AR(El-6|w%_I;17I@&2MZ7>8EjHzssEeUcc>gE+ zZ*8A7ho%EdK69sveSW?*+Wm{wI@OhO_0K0^77SmD%Od>4s=bbWd@O+dt@`eT~-A1**XJ=iaY!lm=Ie|V|I$02qE zAIfz4>u=%5)0|K}^PM4TBc+}NIh??>?~`o$9Y)%(Nw4N}eEji(@Ra%mFLK+YO;rZG zRm=f;MC)iCAR4x4Z-rp(tE_+281yqtMS1S96H6T+KTu`6fr#g^_q)Q?D<9Hv7{=Z` zlA1S~*0iU+;bN8-uU#ap8d~ty%N^GL%pSPt;NW`-QYu#8B=P<|zcXzE=1lCS)?+r; zp>_wa5qC&g{Km^5C{j}H?hRt<<|!I&8X;m&`Xa`agN!tjh5~q!^$zG|GCl51!I|QZ zU-cu;Fw59vQkUq}3E*;9ABueu+gkz@lly|(R89`v-_dEn678gzM9=Vc`FV951yWxd zf^i1W(?x%u6IZv~*U13B-$6B1Iux7o-gxcO%4DJoLfJhO<;f4h7 z>XH6P!Zl#rGC|=9C{p`kh5(A~eWT8RSD(Z~q zscY<&>@G^*U|v3n|CI=4X*Nm8JJ1~h0fDY>s=0umx&Xl98YJZmD5PB!;M;m71}&FE zf=f?ypJa%*^`8yQ15!$UExb*dFY^ROf(+7 z{GmGd<_87_zB9potDqKcg1rF5rt3%_J5}$l0=HwQ32-G5!_ZJb)rm|qRdg!y#dy|j zSIW2Q>QkU#8i6HP_!g)=#^s~1uaRZ9tWO30>Uz3~lT&|1% zY1_WrUCr9kSkCpBvfG{eb8E$lQpyuW5o^ox8fhrd%WJPr0Q&O>W_|qraW!DEhqVC> zlBH}vmpkM%a{Zujr?jl~G8{GS>C;)Dq5`n^<(?btqdNd=D!oPeVcYcvCjg+^cUJ*- z!xAyCJoY4BQ_G4tK5_(fgRzbT(B^$)rYHL;Ks5Qi?-5D?QgD?GxhR`<`7#U_TC&VK zZw|FXQ_EffAm)Qp(^Z(6Z#wX;I~q_34>X8iqyE_lH+oz_P}Y2mf%FL&#Ocu5*1bTp zouNeqV{umpKsZ(BLw$XLms4Y6g1nTo>;0rK9KcLjqX;N@wWY<-BaYy^P(Q zfEVSQf`b|#PM)9SE;L||;qRXpwj~;xnwuIzCJ5kyY6aFksyH)m+s5~^IXin+OQ$B< zp&-x5I3)>ayC`x&Issimkv4!NwoUL?jW%dcJ&QC;I=G#7>}sE~${7xaPJ2U)Wy$k~ z-u|5W>E{XDk2(dJ;G!9s%%x-NSc{P~c=xUb zfT41#-X?=9R=FbV~D68R;?Z}2>PN6KrM@@JowB` zqkjcD#u*EoEn^FT@D0TjjmNi-``BevIMmO7T3&;=rV?|EPfVm8>B)L)&cM;56|VL~ z*Y{Ws541V-Xa=`0jgV^;u)Ya%h6YcQ{nar*WqcwIawyelX=D$>(+e0Pr^7R><@q75 ziV`z9*-eHi)gX{Ibf;l*(ovJ&4ixOWN=e}GeIwFiIweler@oW@i3@-93$4sn@O)ME zy~*=m8n-+QQXS+CJkB7%a4W09w?VTTx}CZgYy%CUnCLylEuIE87yWAk_q~L4?9$_G zsX*J*e)c2oY4{E}1^+}2qX?_Zk3uReVfl|p5~sKS?o4s!znhDufIPnS1LXbgY3^a( zS_rxQPs_1BUaA>j8gSYTB)Z6alI*_>$Pd&fjvf(*$nA?;SOS-)+wrzAFTTArtz5&C zz8!XX^_`h23)il#>H7d{4)HCzEH__%LpJm2NS(ubmpJynAq?xw?+2z=CiUc(w=P-K z3mo|^UFPRO`kD&FSyeGV|8$hvE(0#(1n-zo>-$!oH`gFXENfF+=y4r!Z&!H`9nY-M zzno>Cb;SO7czGuJF+v|S#ympNEQMInyEDm&`bXI6r9IGGec*B(gnpFued+g`pON^f zTt*Mu#w+NK?K@11juX)vjnD6fK z)3{}o;>eQWJ@M2ZT-Z|$T!K4a{E`Ri9|r4b66uoMJWz;KQBzg@m{;*`w4)dPU!AQXxi^3ODvXbZcsy>EKngd(@ORR89(TU%OH6s@) zjEO5y#P*TCch#^NS2$Fm`cwR>ET|S-$~Juxk1{vEoW+GyO7y$|1|gbvQ=ANGSYLG% zGwF?HD82yOrye3t44*}$&?%`zx2=_Nx^}E^@Y@J-X*-P`*njRKFdeXhu` zoq?J`3-Vb`7`xxN9u=$l3&pIAdL-q@l}4Ib;z-4hR?d?Cach6$J+a$c%19Ei|2C|u zskrwEefJ|dBZ5KZV}~BAb0_i~iz+r(SR~Kt>q?uVC6ugPLpEMh8Zndwb3`;NdlC~| zNhGzbiK)aD7T^TKudO-0w&8Rbsnd&|`h=?$ z=baNU#?vlYkX!@B!?zRjxXuzR*)}N%xxvWnmN3n#ug=_k40LAz!WinnqB3F&?zEOXHko zpjMz*h8=Wvqx9@_`yGEr%5xyGuv9Zmj}q_qG~ABy3bLdlI3WB#`0xKkgwxjY0RvYr zkaGgrKgZRD4JITdVN(b>0%OE}ShmtdjJd-6>+PwsEU5hLAn$OVg^eY||1gl6fPi2+ zVUZ?X%LD8KrMfkLZ~`u5Mrgt#B8G+5BEj@Gu&FMG=;ria*&I|**Kwc}fseUvkI6ZN z*}wYo7f*p=6wKfExjD2YdJ#}w0>Cx=BMcOl9)ZT($3}k``0)9-L1kvRa`8N{B!WRG zX=lJh^}gv>O)c(7+y;i3ac>u6AuZO;SyEO3A(Ss*>}X10`#jI+j4Eu*+c}>F@*zr| zqb*L`BVPj*1*-X_-*W>mIT-H;47TrkVPh}BbU z9*cSzu`_J-24qcYuZ>_Pc}x!4jr_&@AwvvI1;+)qm!Zh`RW&LKKETinwxeD^>j$Ac zlJq(@g_dU|Cwl;gS~Qh7nWPOs^!FvPL$X3ZgKki`4+Y|;HGpXKU9{-_%iBveh=Ipo zKd>!_e=XbuS(A|h!UJIcy{|(mBmr{bQ$Tx^ud9;?JFg=>rg$-20g6o{6Bry+II=RQ z#6S0uXZ-}TLy(KISDHPa$NF+m z16X}r{n#EU*X9knh}21674pb~RmAZCC-}AfAeK4vx0pz;g|*|J-u4FG^>*40=}{9o z{a=8vzX2Ap^}>YHk4|1wGsG5tU?gq@fAh42&H4TxJcuW#!?0=u)(M=aRysr20fFv; zi)Igljxb_NNboPNui({TCq*(mv(KRwh=HH+}}xnTEx-P`x|o@-=Ao zl+`sT5?xI6P|GKX*S9HN{onLUtU!IK>o&Svg>!quL|N6 zRE)VVga^^cwOfWxXan<4(`6L73@dQMoqnEb%`$ zbHlYf5o^Q?ocbL6RF6VZ($vkdoUeB6b#q$1t6J6Xlf&}~U)OO}AO?RSCp~lUFA#qc zZ|vj{wrFrxljv}?4lUs&v15B1Gqlc6+LXmsQ=j@H2$t8~p;HJkC2JiB9;db96wFuS(Cg=}Az$f@QU8si$+lt34`K zLNs`5;%?iQDtCj4SRHJi_;zY(le`{^8=^4xQ0Y%9?282OXlJYZE4rPaF z?HKfAM8$MI#di_$oJiNN4r{zV+~vL${t)RkwfB=P3*+N(f*4-P1BmYK!%pU8jG2t+ zjjTE)t_(e?0Q-gmVOJttaz>zDwB(zS^(ecju8JA$G8bUyDtkr57W}=dH>y^gQ=DHG zLpy1y>$OjU2_5rB{wzHhF7u@xOF$y8(5{xITXyquf+DtM$6 z5>Z)IfOl_LlA4a4-g$t2R@ddr6Q%qbH6>Cu<1jruA0A(^lQiZ~MOz}UA&s(voM^Zc z#1U;M>uqi7Z9?X8zRAW>CTcS4Eg2Szr9tH<55*!q`PUH%JjrHZsLEy7?#vJ_1r)^k?DB(05+VmtZ20F2%T&%p82vtpr86*?9e z&7n)?LR;xRi@Kfw_AOBLr(XEZ*k0PpOSr@RRq}nsF8u^Bu=qS9^RP`YDpX8j<5tAe zip;{m#B^GlNgk40g9tfC5@0O-;1!Q3Nlw2!nTvx}3|+bO?E5h6OqbPkJdva$#xwm@A`qCxy^A%7Qk1 ztWPT`zaC=K+IF;|Uu_6+b5B?meo*;Xvhn~xS7Fm%xc*AY?ayU%<8zmk4<=~a6hk#E zYFZKSv*AFGY^0#|f?@@H_6iBJAHK)T$sHUOc?@DkG*Ng`V=RbjHe5pqcZl81n=lu`NYu{*z-d;1Lk@)f@Hx-7Epbe$}fQhprAG0p6fAlj)F zLY{3cEvirTJA=8K@HEe-%u%S>G?|2NeN;R*(Fw5JvkZh9HDqo7jyLQ3_3+&=h!c%| zG($Y&FdW8a)7J?Pn+bPr3ol7d0%6j9Y&THiKvE)gW%GvGLIA9Kz0N3aoEtw62>%cabOG`$Nc!^GN(3#nqlJ zsD87vxwDP1M64$W{-824-5s{Ew$>_{oo`kx$WO@jerH7e4H20W^z-XQ=CB4i*a(X4tz@xtH;R>={)+wkVpAoT>sN2kPu%!qAlC?ic%+}XN zOSRdj2K_vX(2+#5C*5|s-|T{8Vx7-A*@Y}fuaRlVpx&#FGnS$o!_}TX_^py~e9wdP zcCM?R5mdEd@}@R7t!c?zA#mXwHj|=`RxY!F&7p3DE7tiLIKT2w%yYjpVSX-&7$U9w z-Bgm^S&-9SrzGP#y7f(xI45{ao2bp6Rbk}q?%Y~e)MrB8@_VsiW%Z0UDE1;gcqbv7E;QCD7ZA+4lXE5S;CYZrfL3$=6x=&4Rrc6Os~TrKPYs_2AYX*h~9Ok4SA6B(OZf0_RTwlv$UY>4^c6R5u zy&d!}G~S%NaDOjptqs!U)|Rl46YMTtr@PJUt| z)g*xI<3=)4g)I3_bLwWI&c~>2KX^A^5AJ^BQ{L)6)R^X4 zt3BfWJFT(P@Ia38`1{9=Oolz~=f8KXzg77ppHmn$)!I!KmlS<->Ak*Pz>E-?Sg?yu z8qx|um-|*;?b2jMxa9i8_T`lB{P$Aj=+HQd7{Y?M{q8-jlDIn(j#R?Mz zd*-3AqV}7O^9n{I41BFb%&}Ufh1N#be$Fz8!_}X;k}o#hgnDf&P%IyJs~DGc4(#sB zL?UO6;tKLK|NSV;KfGoQJ{fgk32}Wb(hr##^u~7>otbt+cqm-^N7vVF9q&ej7dVr; z^WCL>LOz4`f=X1QDs$kss$c!(3?i+?IMTVDJg6u`RfbhVs=GOI5ke2(>LcFYvWTjD z5zf}Rq!rE}FvaEzME~N7)I8FeT94jUY{WRcwBKRQ{6&mN*++lFDI@)Ut+Mx(&E8YA z-FBV+E8}vBY>`jIrxA)pR%+ELAH{dDv(=6KU%`FxufHM5?aglbsn((%;8|4^6dNz3 z)sSB$5RFVEy(^YmC*?FW_%c;eztG>0RXuh8%v=*Ge^sNoKWF@YikMcFEsc|AvpUT= zX`-Wb)gMZ}dzrks+MR28pk7n$s~`HQR&%cLj30nTw&~Wsq3}2L!VG=h_+HC)fvB(J0Gofe@jDA4!6d;11afp z%I$dh+zHg0&qzuzNcm+|x0`#O#VaJA`SOa|0s$P_Gq&&X&og*!Sf}jM&u98M`+saZ zw`prGqg@X)u@Zhc+(8?SI1B7Pm~BhmoFW(l`J3?DvEWraAipJ;wXGuSBov(1);oSJF=o>Z{2$!N2fiYGk-H6*uNMi`O{4 zEY{I)!BeVyQ?5m(E1?CD$nZBar66!&nwH0DE{D;FTiWlDYvVvoY zBZear#_aFk!$wB*TPMP>=wQ1x-BjU`4{;?nE1Hde?$zLOfvv#y;sXeduJ=7SZu%aq?y*ykwYG}pE{h){i5^Y=}QlOck0&i8sn&Q zyBf}}BNO^Yk@?SCt)r$wT`NeN_{jvH~!ByJ3+fXO`%dRyW@VX0MJU0 zen-KpFuD? zP1s4acGe@LndL2P=uOe2IR}U;LosH;7u{~J5lMdCsE8CtF-O_`5Yu86Nv=Go&Ghh} z-pY{>wmwsex%2%Os$TfMI*!pUMi zjEfu-a^kk56X=Xa!S?>0O7hRW=$@4=X-g{s+_fcd?}T4YT(5hPXb(f)4MngM60Fy4 zFVuW!pBO|$!j5O*@a{|>{4dE?FEafKGaxQNkw=Zme&6Pwr1TqgQ7R=bHc@JN2PEQp zHFJD1^vp@<{?tD0oujiJkVdOb{a`m8OSnU5|+AT_L6&1Uo}*D?(ENLPb8sv3K2)yqCGU41Wk*4 z*m(rna5FAZHqiMo6aB3br#tBw%KJKB^{J06UwQM^_~-Cimh3v(%g_Enx_h+{c9UQ^5l}91B}g8G&5BEo<)G)11Z!k({+V3t#hGM5!PfC`){r zJty_Ok67ZNoSlL>_NUZIa^qu2Sbz_E$bEJSj~zG7t5T}#;0}xsoXm(N&26Uj6LDky z=28;kL~m_fIIP!VZ(?U8HAh)nBC15;zjHl4EN;mY_k4-%JJWhRI+;l;SzXsyxrK`N zpTy?IkVQuEcQOVAk0-o@C2Hi?!OgZ@v8T~`C_VAfgXcEtUU^NXQF|Yd?_hQnP(Njl zjGsNU>#fl-h-ufEPU)t{>tWdu6j(nL8c!GqBwY>nYpth67pNShPf$)OoGGv;q0URU z2pn#?&9$DJ>@GiU6^~)?F=9$yx6)AbJ>b_LuD*>#Xgd!b5!K!IRXkp~5Yt(gT9_89 z$+!Kre_p6Zo#sE(lja>^ha_NLn1(8NN)XHIZV4qGyrzR|q`#li9RKN|TPZdaNz@c3 zOO_3uu!TMNF+QLRsF zHHk8{`>3Qh3rb=ie1X+5V>u3tACx8>Jny^lY9VL5X3cQ05(s#d>8Nh@uvX-0$VSxf zEJgT`%s9$i+UfTgOSL~yoeU08$O{n%s$;%RNY}^*xb>MPbA}*!Tq9TI#L1?Z)_@9P z;?+4j=SqWa|KpU0c!7Bw=?_i>l=hXGNlg{1pU$yLnuX{HxS6HPEoLdYK(55JCBfZFvRonbuX*C*oU_=d<8kU=HG9Bj zJkn))@UhUs+j_2c?*kI@Y@Ndr_y_JuRzI8=gn){$>!{Yfis9IMe7XzvME#}x;9OLK zGZuD8-PfKmfzurWp`7=sQda^C5j#9ciCU%a+rHX=Is(I{Jk}Ouy3|f?BSfeqxLYKe z;_XC>%hg6vD~xZV#H9)EM$}=h$mI8IR1%W;V69u2nLPHEhVH!oMp|P!{@mFBNjdYB5}l^e zYW><{C;`e`0+DZxv!9edG%<0OmBBP$ufK4 zgZSX0f&Lve{wNCVk65ee-CaboD(b}|5C6;{`RP^HSX96D&cAB1A zj^tY9(5xkavTrhTX|uDIte*)EdxqqfEA$%GM9$ryZ=S+x73&}^0)x^u6#|8#NlU1_ zT6ISHy5Ag?&QYnFG&L()1O7@&<8-G%tIy(zRlbP2eQo_oyk#D{3ZNG;n_|C#p~?dh zLVsSuWC^d%kl9pBR$}(M$uFJK+{Ut{-Q z9q(dbRskGgJ{+sR-EzlU^eGcD9-JtO#c{i+oPW(ne|%B0SEsI_SAp!YuN)w;SJmi* zlw{WZkZ zjS#4T-j6CW@-&IPFiQwvA-8{52KZ+t`!r`faNnUE$R{bXm8A-jaOqF$i6e^HsHN5* z?t$wd`T3laH$odL80+ANIcM1^N{U|rs%n$aUUXMCm>QxbkLT3IhT@wHJl$?KtEiCI zudwtz-h2Le{{VGZ3)9&AM_(ub-N#0XTcdJeGvCGXSg)QqOEF2|XHdV^DH?TLj%hjs zVequK)5A#2ZaGCpji=96hfiE+WhuzAFh|pEQ?tLjas Date: Thu, 24 Sep 2026 11:32:57 -0700 Subject: [PATCH 6/8] WEBDEV-9038: Register the topnav elements with the guarded customElement Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_013RS8ThjiMNiq7HBBAGash1 --- src/elements/ia-topnav/ia-topnav-desktop-subnav.ts | 3 ++- src/elements/ia-topnav/ia-topnav-icon-hamburger.ts | 2 +- src/elements/ia-topnav/ia-topnav-login-button.ts | 3 ++- src/elements/ia-topnav/ia-topnav-media-button.ts | 3 ++- src/elements/ia-topnav/ia-topnav-media-menu.ts | 3 ++- src/elements/ia-topnav/ia-topnav-media-slider.ts | 3 ++- src/elements/ia-topnav/ia-topnav-media-subnav.ts | 3 ++- src/elements/ia-topnav/ia-topnav-more-slider.ts | 3 ++- src/elements/ia-topnav/ia-topnav-primary-nav.ts | 3 ++- src/elements/ia-topnav/ia-topnav-save-page-form.ts | 3 ++- src/elements/ia-topnav/ia-topnav-signed-out-dropdown.ts | 2 +- src/elements/ia-topnav/ia-topnav-story.ts | 3 ++- src/elements/ia-topnav/ia-topnav-user-menu.ts | 3 ++- src/elements/ia-topnav/ia-topnav-wayback-search.ts | 3 ++- src/elements/ia-topnav/ia-topnav-wayback-slider.ts | 3 ++- src/elements/ia-topnav/ia-topnav.ts | 3 ++- 16 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts b/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts index 09b0a0b8..2ebec751 100644 --- a/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts +++ b/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts @@ -1,5 +1,6 @@ import { CSSResultGroup, TemplateResult, css, html, nothing } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; +import { property } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import TrackedElement from './tracked-element'; import icons from './assets/img/icons'; diff --git a/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts b/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts index adc5358c..fbcdc16a 100644 --- a/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts +++ b/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts @@ -1,7 +1,7 @@ import { html, css } from 'lit'; import Icon from './assets/img/icon'; import icons from './assets/img/icons'; -import { customElement } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; @customElement('ia-topnav-icon-hamburger') export class HamBurger extends Icon { diff --git a/src/elements/ia-topnav/ia-topnav-login-button.ts b/src/elements/ia-topnav/ia-topnav-login-button.ts index 038a2662..fa35f018 100644 --- a/src/elements/ia-topnav/ia-topnav-login-button.ts +++ b/src/elements/ia-topnav/ia-topnav-login-button.ts @@ -3,7 +3,8 @@ import TrackedElement from './tracked-element'; import icons from './assets/img/icons'; import formatUrl from './lib/format-url'; import { makeBooleanString } from './lib/make-boolean-string'; -import { customElement, property, query } from 'lit/decorators.js'; +import { property, query } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; import { defaultTopNavConfig } from './data/menus'; import themeStyles from '@src/themes/theme-styles'; diff --git a/src/elements/ia-topnav/ia-topnav-media-button.ts b/src/elements/ia-topnav/ia-topnav-media-button.ts index c022fc6f..27ba523d 100644 --- a/src/elements/ia-topnav/ia-topnav-media-button.ts +++ b/src/elements/ia-topnav/ia-topnav-media-button.ts @@ -2,7 +2,8 @@ import { CSSResultGroup, TemplateResult, css, html } from 'lit'; import TrackedElement from './tracked-element'; import icons from './assets/img/icons'; import toSentenceCase from './lib/t-sentence-case'; -import { customElement, property } from 'lit/decorators.js'; +import { property } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; import { defaultTopNavConfig } from './data/menus'; import themeStyles from '@src/themes/theme-styles'; diff --git a/src/elements/ia-topnav/ia-topnav-media-menu.ts b/src/elements/ia-topnav/ia-topnav-media-menu.ts index eb1a4f71..df255f5a 100644 --- a/src/elements/ia-topnav/ia-topnav-media-menu.ts +++ b/src/elements/ia-topnav/ia-topnav-media-menu.ts @@ -1,5 +1,6 @@ import { CSSResultGroup, LitElement, PropertyValues, css, html } from 'lit'; -import { customElement, property, queryAll } from 'lit/decorators.js'; +import { property, queryAll } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import { defaultTopNavConfig } from './data/menus'; import formatUrl from './lib/format-url'; diff --git a/src/elements/ia-topnav/ia-topnav-media-slider.ts b/src/elements/ia-topnav/ia-topnav-media-slider.ts index c75ae43b..9cd39d27 100644 --- a/src/elements/ia-topnav/ia-topnav-media-slider.ts +++ b/src/elements/ia-topnav/ia-topnav-media-slider.ts @@ -1,7 +1,8 @@ import { CSSResultGroup, LitElement, PropertyValues, css, html } from 'lit'; import './ia-topnav-media-subnav'; import KeyboardNavigation from './lib/keyboard-navigation'; -import { customElement, property } from 'lit/decorators.js'; +import { property } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import { IATopNavConfig, IATopNavMenuConfig, diff --git a/src/elements/ia-topnav/ia-topnav-media-subnav.ts b/src/elements/ia-topnav/ia-topnav-media-subnav.ts index 7d4b4590..e722efae 100644 --- a/src/elements/ia-topnav/ia-topnav-media-subnav.ts +++ b/src/elements/ia-topnav/ia-topnav-media-subnav.ts @@ -6,7 +6,8 @@ import './ia-topnav-wayback-slider'; import './ia-topnav-more-slider'; import toSentenceCase from './lib/t-sentence-case'; import formatUrl from './lib/format-url'; -import { customElement, property } from 'lit/decorators.js'; +import { property } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import { IATopNavConfig, IATopNavLink, diff --git a/src/elements/ia-topnav/ia-topnav-more-slider.ts b/src/elements/ia-topnav/ia-topnav-more-slider.ts index c4ee0fb9..63276814 100644 --- a/src/elements/ia-topnav/ia-topnav-more-slider.ts +++ b/src/elements/ia-topnav/ia-topnav-more-slider.ts @@ -1,5 +1,6 @@ import { CSSResultGroup, css, html } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; +import { property } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import TrackedElement from './tracked-element'; import toSentenceCase from './lib/t-sentence-case'; diff --git a/src/elements/ia-topnav/ia-topnav-primary-nav.ts b/src/elements/ia-topnav/ia-topnav-primary-nav.ts index 97b79be1..b419c7d7 100644 --- a/src/elements/ia-topnav/ia-topnav-primary-nav.ts +++ b/src/elements/ia-topnav/ia-topnav-primary-nav.ts @@ -7,7 +7,8 @@ import type { LoginButton } from './ia-topnav-login-button'; import './ia-topnav-media-menu'; import logoWordmarkStacked from './assets/img/wordmark-stacked'; import formatUrl from './lib/format-url'; -import { customElement, property, query } from 'lit/decorators.js'; +import { property, query } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import { IATopNavConfig, IATopNavSecondIdentitySlotMode, diff --git a/src/elements/ia-topnav/ia-topnav-save-page-form.ts b/src/elements/ia-topnav/ia-topnav-save-page-form.ts index 6523330f..e044a79d 100644 --- a/src/elements/ia-topnav/ia-topnav-save-page-form.ts +++ b/src/elements/ia-topnav/ia-topnav-save-page-form.ts @@ -1,6 +1,7 @@ import { CSSResultGroup, css, html } from 'lit'; import TrackedElement from './tracked-element'; -import { customElement, property, state } from 'lit/decorators.js'; +import { property, state } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; import { defaultTopNavConfig } from './data/menus'; import themeStyles from '@src/themes/theme-styles'; diff --git a/src/elements/ia-topnav/ia-topnav-signed-out-dropdown.ts b/src/elements/ia-topnav/ia-topnav-signed-out-dropdown.ts index 9f08e954..248b7f4e 100644 --- a/src/elements/ia-topnav/ia-topnav-signed-out-dropdown.ts +++ b/src/elements/ia-topnav/ia-topnav-signed-out-dropdown.ts @@ -1,4 +1,4 @@ -import { customElement } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import DropdownMenu from './dropdown-menu'; @customElement('ia-topnav-signed-out-dropdown') diff --git a/src/elements/ia-topnav/ia-topnav-story.ts b/src/elements/ia-topnav/ia-topnav-story.ts index 04b71cbf..405586b2 100644 --- a/src/elements/ia-topnav/ia-topnav-story.ts +++ b/src/elements/ia-topnav/ia-topnav-story.ts @@ -1,5 +1,6 @@ import { css, html, LitElement, type CSSResultGroup } from 'lit'; -import { customElement, state } from 'lit/decorators.js'; +import { state } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import './ia-topnav'; import type { PropInputSettings } from '@demo/story-components/story-prop-settings'; diff --git a/src/elements/ia-topnav/ia-topnav-user-menu.ts b/src/elements/ia-topnav/ia-topnav-user-menu.ts index f8ce6b40..ebb60ed9 100644 --- a/src/elements/ia-topnav/ia-topnav-user-menu.ts +++ b/src/elements/ia-topnav/ia-topnav-user-menu.ts @@ -1,6 +1,7 @@ import { html } from 'lit'; import DropdownMenu from './dropdown-menu'; -import { customElement, property } from 'lit/decorators.js'; +import { property } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; @customElement('ia-topnav-user-menu') export default class UserMenu extends DropdownMenu { diff --git a/src/elements/ia-topnav/ia-topnav-wayback-search.ts b/src/elements/ia-topnav/ia-topnav-wayback-search.ts index 4565ac1d..f31cd7e0 100644 --- a/src/elements/ia-topnav/ia-topnav-wayback-search.ts +++ b/src/elements/ia-topnav/ia-topnav-wayback-search.ts @@ -1,5 +1,6 @@ import { css, CSSResultGroup, LitElement, html } from 'lit'; -import { customElement, property, query } from 'lit/decorators.js'; +import { property, query } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import searchIcon from './assets/img/icon-search'; import logo from './assets/img/wayback-logo'; diff --git a/src/elements/ia-topnav/ia-topnav-wayback-slider.ts b/src/elements/ia-topnav/ia-topnav-wayback-slider.ts index 0edd6dc0..b46c0a63 100644 --- a/src/elements/ia-topnav/ia-topnav-wayback-slider.ts +++ b/src/elements/ia-topnav/ia-topnav-wayback-slider.ts @@ -5,7 +5,8 @@ import './ia-topnav-save-page-form'; import queryHandler from './lib/query-handler'; import toSentenceCase from './lib/t-sentence-case'; import formatUrl from './lib/format-url'; -import { customElement, property } from 'lit/decorators.js'; +import { property } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import { IATopNavConfig, IATopNavLink, diff --git a/src/elements/ia-topnav/ia-topnav.ts b/src/elements/ia-topnav/ia-topnav.ts index 93b302aa..0880eb45 100644 --- a/src/elements/ia-topnav/ia-topnav.ts +++ b/src/elements/ia-topnav/ia-topnav.ts @@ -6,7 +6,8 @@ import { html, nothing, } from 'lit'; -import { customElement, property, query, state } from 'lit/decorators.js'; +import { property, query, state } from 'lit/decorators.js'; +import { customElement } from '@src/util/custom-element'; import { buildTopNavMenus, defaultTopNavConfig } from './data/menus'; import './ia-topnav-desktop-subnav'; From 4ba2602fbfcfe0da9404ae1d7b2e7fab4aafc813 Mon Sep 17 00:00:00 2001 From: Jason Buckner Date: Wed, 30 Sep 2026 14:59:22 -0700 Subject: [PATCH 7/8] WEBDEV-9038: Put the topnav components' members in house order Move only, no behaviour change. In each component the properties come first, then lifecycles, then render, then the helpers, with styles at the bottom. A diff review checked it at the class-member level: every member is byte-identical to before, only its position moved, and instance fields keep their relative order. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HjwDQaR3hvZ8J2PP4117W2 --- src/elements/ia-topnav/dropdown-menu.ts | 198 ++-- .../ia-topnav/ia-topnav-desktop-subnav.ts | 62 +- .../ia-topnav/ia-topnav-icon-hamburger.ts | 26 +- .../ia-topnav/ia-topnav-login-button.ts | 128 +-- .../ia-topnav/ia-topnav-media-button.ts | 158 +-- .../ia-topnav/ia-topnav-media-menu.ts | 134 +-- .../ia-topnav/ia-topnav-media-slider.ts | 186 ++-- .../ia-topnav/ia-topnav-media-subnav.ts | 194 ++-- .../ia-topnav/ia-topnav-more-slider.ts | 44 +- .../ia-topnav/ia-topnav-primary-nav.ts | 928 +++++++++--------- .../ia-topnav/ia-topnav-save-page-form.ts | 96 +- .../ia-topnav/ia-topnav-wayback-slider.ts | 124 +-- src/elements/ia-topnav/ia-topnav.ts | 286 +++--- 13 files changed, 1282 insertions(+), 1282 deletions(-) diff --git a/src/elements/ia-topnav/dropdown-menu.ts b/src/elements/ia-topnav/dropdown-menu.ts index 2833c04f..3c3c0c29 100644 --- a/src/elements/ia-topnav/dropdown-menu.ts +++ b/src/elements/ia-topnav/dropdown-menu.ts @@ -32,6 +32,105 @@ export default class DropdownMenu extends TrackedElement { private previousKeydownListener?: // eslint-disable-next-line @typescript-eslint/no-explicit-any (this: HTMLElement, ev: KeyboardEvent) => any; + updated(props: PropertyValues) { + if (props.has('open') && this.open) { + const container = this.shadowRoot?.querySelector( + '.nav-container', + ) as HTMLElement; + + if (container) { + const keyboardNavigation = new KeyboardNavigation( + container, + 'usermenu', + ); + this.addEventListener('keydown', keyboardNavigation.handleKeyDown); + if (this.previousKeydownListener) { + this.removeEventListener('keydown', this.previousKeydownListener); + } + this.previousKeydownListener = keyboardNavigation.handleKeyDown; + } + } + } + + render() { + return html` +

    + `; + } + + get dropdownItems() { + if (!this.menuItems) return nothing; + + if (!Array.isArray(this.menuItems[0])) { + const submenu = this.menuItems as IATopNavLink[]; + return this.dropdownSection(submenu); + } + return this.menuItems.map((submenu, i) => { + const joiner = i ? DropdownMenu.dropdownDivider : html``; + if (!Array.isArray(submenu)) { + return; + } + return [joiner, ...this.dropdownSection(submenu)]; + }); + } + + static get dropdownDivider() { + return html`
  • `; + } + + private dropdownSection(submenu: IATopNavLink[]): TemplateResult[] { + return submenu.map( + (item) => html` +
  • + ${item.url + ? this.dropdownLink(item) + : DropdownMenu.dropdownText(item)} +
  • + `, + ); + } + + dropdownLink(link: IATopNavLink): TemplateResult { + const calloutText = this.config?.callouts?.[link.title]; + const isMobileUpload = link.class === 'mobile-upload'; + const isTabbable = this.open && !isMobileUpload; + + return html` + ${isMobileUpload ? icons.uploadUnpadded : nothing} ${link.title} + ${calloutText + ? html`` + : nothing} + `; + } + + static dropdownText(item: IATopNavLink) { + return html`${item.title}`; + } + + get menuClass() { + if (this.open) return 'open'; + if (this.animated) return 'closed'; + return 'initial'; + } + static get styles(): CSSResultGroup { return [ themeStyles, @@ -220,103 +319,4 @@ export default class DropdownMenu extends TrackedElement { `, ]; } - - updated(props: PropertyValues) { - if (props.has('open') && this.open) { - const container = this.shadowRoot?.querySelector( - '.nav-container', - ) as HTMLElement; - - if (container) { - const keyboardNavigation = new KeyboardNavigation( - container, - 'usermenu', - ); - this.addEventListener('keydown', keyboardNavigation.handleKeyDown); - if (this.previousKeydownListener) { - this.removeEventListener('keydown', this.previousKeydownListener); - } - this.previousKeydownListener = keyboardNavigation.handleKeyDown; - } - } - } - - get dropdownItems() { - if (!this.menuItems) return nothing; - - if (!Array.isArray(this.menuItems[0])) { - const submenu = this.menuItems as IATopNavLink[]; - return this.dropdownSection(submenu); - } - return this.menuItems.map((submenu, i) => { - const joiner = i ? DropdownMenu.dropdownDivider : html``; - if (!Array.isArray(submenu)) { - return; - } - return [joiner, ...this.dropdownSection(submenu)]; - }); - } - - static get dropdownDivider() { - return html`
  • `; - } - - private dropdownSection(submenu: IATopNavLink[]): TemplateResult[] { - return submenu.map( - (item) => html` -
  • - ${item.url - ? this.dropdownLink(item) - : DropdownMenu.dropdownText(item)} -
  • - `, - ); - } - - dropdownLink(link: IATopNavLink): TemplateResult { - const calloutText = this.config?.callouts?.[link.title]; - const isMobileUpload = link.class === 'mobile-upload'; - const isTabbable = this.open && !isMobileUpload; - - return html` - ${isMobileUpload ? icons.uploadUnpadded : nothing} ${link.title} - ${calloutText - ? html`` - : nothing} - `; - } - - static dropdownText(item: IATopNavLink) { - return html`${item.title}`; - } - - get menuClass() { - if (this.open) return 'open'; - if (this.animated) return 'closed'; - return 'initial'; - } - - render() { - return html` - - `; - } } diff --git a/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts b/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts index 2ebec751..0f2c0ba6 100644 --- a/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts +++ b/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts @@ -13,6 +13,37 @@ export class DesktopSubnav extends TrackedElement { @property({ type: String }) baseHost = ''; @property({ type: Array }) menuItems: IATopNavLink[] = []; + render() { + return html` +
      + ${this.listItems} +
    + `; + } + + get listItems() { + return this.menuItems + ? this.menuItems.map( + (link) => html` +
  • + ${link.title}${DesktopSubnav.iconFor(link.title)} +
  • + `, + ) + : nothing; + } + + static iconFor(title: string): TemplateResult { + const subnavIcons: Record = { + Donate: icons.donate, + }; + return subnavIcons[title] ? subnavIcons[title] : html``; + } + static get styles(): CSSResultGroup { return [ themeStyles, @@ -54,35 +85,4 @@ export class DesktopSubnav extends TrackedElement { `, ]; } - - get listItems() { - return this.menuItems - ? this.menuItems.map( - (link) => html` -
  • - ${link.title}${DesktopSubnav.iconFor(link.title)} -
  • - `, - ) - : nothing; - } - - static iconFor(title: string): TemplateResult { - const subnavIcons: Record = { - Donate: icons.donate, - }; - return subnavIcons[title] ? subnavIcons[title] : html``; - } - - render() { - return html` -
      - ${this.listItems} -
    - `; - } } diff --git a/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts b/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts index fbcdc16a..0c6b4f03 100644 --- a/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts +++ b/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts @@ -5,17 +5,8 @@ import { customElement } from '@src/util/custom-element'; @customElement('ia-topnav-icon-hamburger') export class HamBurger extends Icon { - static get styles() { - return css` - svg { - display: block; - height: 4rem; - width: 4rem; - } - .fill-color { - fill: var(--activeColor); - } - `; + render() { + return this.active ? HamBurger.opened : HamBurger.closed; } static get closed() { @@ -43,7 +34,16 @@ export class HamBurger extends Icon { return icons.close; } - render() { - return this.active ? HamBurger.opened : HamBurger.closed; + static get styles() { + return css` + svg { + display: block; + height: 4rem; + width: 4rem; + } + .fill-color { + fill: var(--activeColor); + } + `; } } diff --git a/src/elements/ia-topnav/ia-topnav-login-button.ts b/src/elements/ia-topnav/ia-topnav-login-button.ts index fa35f018..c195fbf5 100644 --- a/src/elements/ia-topnav/ia-topnav-login-button.ts +++ b/src/elements/ia-topnav/ia-topnav-login-button.ts @@ -17,6 +17,70 @@ export class LoginButton extends TrackedElement { @query('button.logged-out-menu') private toggleButton?: HTMLButtonElement; + render() { + return html` +
    + + + Sign up + | + Log in + +
    + `; + } + + /** Distance (px) from this element's right edge to the right edge of the dropdown toggle icon. */ + getDropdownToggleOffset(): number { + if (!this.toggleButton) return 0; + return ( + this.getBoundingClientRect().right - + this.toggleButton.getBoundingClientRect().right + ); + } + + get signupPath() { + return formatUrl('/signup', this.baseHost); + } + + get loginPath() { + return formatUrl('/login', this.baseHost); + } + + get analyticsEvent() { + return `${this.config?.eventCategory}|NavLoginIcon`; + } + + get menuOpened(): boolean { + return this.openMenu === 'login'; + } + + get avatarClass() { + return `dropdown-toggle${this.menuOpened ? ' active' : ''}`; + } + + toggleDropdown(e: Event) { + e.preventDefault(); + this.trackClick(e); + this.dispatchEvent( + new CustomEvent('menuToggled', { + bubbles: true, + composed: true, + detail: { + menuName: 'login', + }, + }), + ); + } + static get styles(): CSSResultGroup { return [ themeStyles, @@ -110,68 +174,4 @@ export class LoginButton extends TrackedElement { `, ]; } - - /** Distance (px) from this element's right edge to the right edge of the dropdown toggle icon. */ - getDropdownToggleOffset(): number { - if (!this.toggleButton) return 0; - return ( - this.getBoundingClientRect().right - - this.toggleButton.getBoundingClientRect().right - ); - } - - get signupPath() { - return formatUrl('/signup', this.baseHost); - } - - get loginPath() { - return formatUrl('/login', this.baseHost); - } - - get analyticsEvent() { - return `${this.config?.eventCategory}|NavLoginIcon`; - } - - get menuOpened(): boolean { - return this.openMenu === 'login'; - } - - get avatarClass() { - return `dropdown-toggle${this.menuOpened ? ' active' : ''}`; - } - - toggleDropdown(e: Event) { - e.preventDefault(); - this.trackClick(e); - this.dispatchEvent( - new CustomEvent('menuToggled', { - bubbles: true, - composed: true, - detail: { - menuName: 'login', - }, - }), - ); - } - - render() { - return html` -
    - - - Sign up - | - Log in - -
    - `; - } } diff --git a/src/elements/ia-topnav/ia-topnav-media-button.ts b/src/elements/ia-topnav/ia-topnav-media-button.ts index 27ba523d..59a6a45c 100644 --- a/src/elements/ia-topnav/ia-topnav-media-button.ts +++ b/src/elements/ia-topnav/ia-topnav-media-button.ts @@ -19,6 +19,85 @@ export class MediaButton extends TrackedElement { @property({ type: Boolean }) selected = false; @property({ type: Boolean }) followable = false; + render() { + return html` + + ${this.menuItem} + + `; + } + + static get icons(): Record { + return icons; + } + + onClick(e: Event) { + this.trackClick(e); + e.preventDefault(); + // On desktop viewport widths, the media subnav is always visible. To + // ensure the media subnav is open on mobile if the viewport is + // resized, the openMenu needs to be set to 'media'. + if (this.openMenu !== 'media') { + this.dispatchMenuToggledEvent(); + } + this.dispatchMediaTypeSelectedEvent(); + } + + dispatchMenuToggledEvent() { + this.dispatchEvent( + new CustomEvent('menuToggled', { + bubbles: true, + composed: true, + detail: { + menuName: 'media', + }, + }), + ); + } + + dispatchMediaTypeSelectedEvent() { + this.dispatchEvent( + new CustomEvent('mediaTypeSelected', { + bubbles: true, + composed: true, + detail: { + mediatype: this.mediatype, + }, + }), + ); + } + + get buttonClass() { + return this.selected ? 'selected' : ''; + } + + get tooltipPrefix() { + return this.selected ? 'Collapse' : 'Expand'; + } + + get iconClass() { + return this.selected ? 'active' : ''; + } + + get analyticsEvent() { + return `${this.config.eventCategory}|NavMenu${toSentenceCase(this.mediatype)}`; + } + + get menuItem() { + return html` + + ${MediaButton.icons[this.icon]} + + ${this.label} + `; + } + static get styles(): CSSResultGroup { return [ themeStyles, @@ -178,83 +257,4 @@ export class MediaButton extends TrackedElement { `, ]; } - - static get icons(): Record { - return icons; - } - - onClick(e: Event) { - this.trackClick(e); - e.preventDefault(); - // On desktop viewport widths, the media subnav is always visible. To - // ensure the media subnav is open on mobile if the viewport is - // resized, the openMenu needs to be set to 'media'. - if (this.openMenu !== 'media') { - this.dispatchMenuToggledEvent(); - } - this.dispatchMediaTypeSelectedEvent(); - } - - dispatchMenuToggledEvent() { - this.dispatchEvent( - new CustomEvent('menuToggled', { - bubbles: true, - composed: true, - detail: { - menuName: 'media', - }, - }), - ); - } - - dispatchMediaTypeSelectedEvent() { - this.dispatchEvent( - new CustomEvent('mediaTypeSelected', { - bubbles: true, - composed: true, - detail: { - mediatype: this.mediatype, - }, - }), - ); - } - - get buttonClass() { - return this.selected ? 'selected' : ''; - } - - get tooltipPrefix() { - return this.selected ? 'Collapse' : 'Expand'; - } - - get iconClass() { - return this.selected ? 'active' : ''; - } - - get analyticsEvent() { - return `${this.config.eventCategory}|NavMenu${toSentenceCase(this.mediatype)}`; - } - - get menuItem() { - return html` - - ${MediaButton.icons[this.icon]} - - ${this.label} - `; - } - - render() { - return html` - - ${this.menuItem} - - `; - } } diff --git a/src/elements/ia-topnav/ia-topnav-media-menu.ts b/src/elements/ia-topnav/ia-topnav-media-menu.ts index df255f5a..9a14bf83 100644 --- a/src/elements/ia-topnav/ia-topnav-media-menu.ts +++ b/src/elements/ia-topnav/ia-topnav-media-menu.ts @@ -71,6 +71,73 @@ export class MediaMenu extends LitElement { @queryAll('ia-topnav-media-button') mediaButtons?: MediaButton[]; + updated(props: PropertyValues) { + if (props.has('currentTab')) { + const mediaButtons = Array.from(this.mediaButtons ?? []); + + mediaButtons.map((button, index) => { + const linkItem = button.shadowRoot?.querySelector('a.menu-item'); + if (linkItem) { + if (linkItem.classList.contains(`${this.selectedMenuOption}`)) { + linkItem.classList.remove('selected'); + (linkItem as HTMLElement).blur(); + + const newFocusIndex = + this.currentTab?.moveTo === 'next' ? index + 1 : index - 1; + ( + mediaButtons[newFocusIndex]?.shadowRoot?.querySelector( + 'a.menu-item', + ) as HTMLElement + ).focus(); + } + } + }); + } + } + + render() { + return html` +
    +
    + +
    +
    + `; + } + + get mediaMenuOptionsTemplate() { + const buttons = menuSelection.map( + ({ icon, menu, label, href, followable }) => { + const selected = this.selectedMenuOption === menu; + return html` + + `; + }, + ); + return buttons; + } + + get menuOpened() { + return this.openMenu === 'media'; + } + + get menuClass() { + return this.menuOpened ? 'open' : 'closed'; + } + static get styles(): CSSResultGroup { return [ themeStyles, @@ -140,71 +207,4 @@ export class MediaMenu extends LitElement { `, ]; } - - updated(props: PropertyValues) { - if (props.has('currentTab')) { - const mediaButtons = Array.from(this.mediaButtons ?? []); - - mediaButtons.map((button, index) => { - const linkItem = button.shadowRoot?.querySelector('a.menu-item'); - if (linkItem) { - if (linkItem.classList.contains(`${this.selectedMenuOption}`)) { - linkItem.classList.remove('selected'); - (linkItem as HTMLElement).blur(); - - const newFocusIndex = - this.currentTab?.moveTo === 'next' ? index + 1 : index - 1; - ( - mediaButtons[newFocusIndex]?.shadowRoot?.querySelector( - 'a.menu-item', - ) as HTMLElement - ).focus(); - } - } - }); - } - } - - get mediaMenuOptionsTemplate() { - const buttons = menuSelection.map( - ({ icon, menu, label, href, followable }) => { - const selected = this.selectedMenuOption === menu; - return html` - - `; - }, - ); - return buttons; - } - - get menuOpened() { - return this.openMenu === 'media'; - } - - get menuClass() { - return this.menuOpened ? 'open' : 'closed'; - } - - render() { - return html` -
    -
    - -
    -
    - `; - } } diff --git a/src/elements/ia-topnav/ia-topnav-media-slider.ts b/src/elements/ia-topnav/ia-topnav-media-slider.ts index 9cd39d27..988cba2d 100644 --- a/src/elements/ia-topnav/ia-topnav-media-slider.ts +++ b/src/elements/ia-topnav/ia-topnav-media-slider.ts @@ -22,89 +22,15 @@ export class MediaSlider extends LitElement { private previousKeydownListener: // eslint-disable-next-line @typescript-eslint/no-explicit-any ((this: HTMLElement, ev: KeyboardEvent) => any) | undefined; - static get styles(): CSSResultGroup { - return [ - themeStyles, - css` - .media-slider-container { - position: relative; - } - - .overflow-clip { - display: none; - position: absolute; - top: 0; - right: 0; - left: 0; - height: 0; - overflow: hidden; - transition: height 0.2s ease; - } - - .information-menu { - position: absolute; - top: 0; - right: 0; - left: 0; - padding: 0; - height: 31.9rem; - overflow-x: hidden; - font-size: 1.4rem; - background: var(--mediaSliderBg); - } - - .open { - display: block; - } - - .hidden { - display: none; - } - - .info-box { - padding: 1rem; - } - - @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { - .overflow-clip.open { - display: block; - height: 35.8rem; - left: 4rem; - top: 0; - } - } - - @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { - .overflow-clip { - display: block; - } - - .information-menu { - left: 0; - z-index: 3; - height: auto; - min-height: 21rem; - background: var(--mediaSliderDesktopBg); - transform: translate(0, -100%); - transition: transform 0.2s ease; - } - - .overflow-clip.open { - height: 22rem; - } - - .information-menu.open { - transform: translate(0, 0); - } + shouldUpdate() { + const scrollPane = this.shadowRoot + ? this.shadowRoot.querySelector('.information-menu') + : null; - .info-box { - max-width: 100rem; - padding: 1.5rem 0; - margin: 0 auto; - } - } - `, - ]; + if (scrollPane) { + scrollPane.scrollTop = 0; + } + return true; } updated(props: PropertyValues) { @@ -126,17 +52,6 @@ export class MediaSlider extends LitElement { } } - shouldUpdate() { - const scrollPane = this.shadowRoot - ? this.shadowRoot.querySelector('.information-menu') - : null; - - if (scrollPane) { - scrollPane.scrollTop = 0; - } - return true; - } - render() { const sliderDetailsClass = this.mediaSliderOpen ? 'open' : 'closed'; @@ -214,4 +129,89 @@ export class MediaSlider extends LitElement { `; } + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + .media-slider-container { + position: relative; + } + + .overflow-clip { + display: none; + position: absolute; + top: 0; + right: 0; + left: 0; + height: 0; + overflow: hidden; + transition: height 0.2s ease; + } + + .information-menu { + position: absolute; + top: 0; + right: 0; + left: 0; + padding: 0; + height: 31.9rem; + overflow-x: hidden; + font-size: 1.4rem; + background: var(--mediaSliderBg); + } + + .open { + display: block; + } + + .hidden { + display: none; + } + + .info-box { + padding: 1rem; + } + + @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { + .overflow-clip.open { + display: block; + height: 35.8rem; + left: 4rem; + top: 0; + } + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + .overflow-clip { + display: block; + } + + .information-menu { + left: 0; + z-index: 3; + height: auto; + min-height: 21rem; + background: var(--mediaSliderDesktopBg); + transform: translate(0, -100%); + transition: transform 0.2s ease; + } + + .overflow-clip.open { + height: 22rem; + } + + .information-menu.open { + transform: translate(0, 0); + } + + .info-box { + max-width: 100rem; + padding: 1.5rem 0; + margin: 0 auto; + } + } + `, + ]; + } } diff --git a/src/elements/ia-topnav/ia-topnav-media-subnav.ts b/src/elements/ia-topnav/ia-topnav-media-subnav.ts index e722efae..6c8001c1 100644 --- a/src/elements/ia-topnav/ia-topnav-media-subnav.ts +++ b/src/elements/ia-topnav/ia-topnav-media-subnav.ts @@ -36,6 +36,103 @@ export class MediaSubnav extends TrackedElement { private links: IATopNavMediaMenu = MediaSubnav.defaultLinks; + shouldUpdate() { + if (this.menuItems) { + this.links = this.menuItems; + } + return true; + } + + render() { + if (!this.menu) { + return html``; + } + + if (this.menuItems) { + this.links = this.menuItems; + } + + if (this.menu === 'web') { + return html` `; + } + + if (this.menu === 'more') { + return html` + `; + } + + return html` +

    ${this.links.heading}

    + + + + `; + } + + static get defaultLinks(): IATopNavMediaMenu { + return { + heading: '', + iconLinks: [], + featuredLinks: [], + links: [], + mobileAppsLinks: [], + browserExtensionsLinks: [], + archiveItLinks: [], + }; + } + + analyticsEvent(title: string) { + return `${this.config?.eventCategory}|${toSentenceCase(title)}${toSentenceCase(this.menu)}`; + } + + get iconLinks() { + return this.links.iconLinks.map( + (link) => html` + ${link.title} + `, + ); + } + + renderLinks(links: IATopNavLink[]) { + return links.map( + (link) => html` +
  • + ${link.title} +
  • + `, + ); + } + static get styles(): CSSResultGroup { return [ themeStyles, @@ -195,101 +292,4 @@ export class MediaSubnav extends TrackedElement { `, ]; } - - shouldUpdate() { - if (this.menuItems) { - this.links = this.menuItems; - } - return true; - } - - static get defaultLinks(): IATopNavMediaMenu { - return { - heading: '', - iconLinks: [], - featuredLinks: [], - links: [], - mobileAppsLinks: [], - browserExtensionsLinks: [], - archiveItLinks: [], - }; - } - - analyticsEvent(title: string) { - return `${this.config?.eventCategory}|${toSentenceCase(title)}${toSentenceCase(this.menu)}`; - } - - get iconLinks() { - return this.links.iconLinks.map( - (link) => html` - ${link.title} - `, - ); - } - - renderLinks(links: IATopNavLink[]) { - return links.map( - (link) => html` -
  • - ${link.title} -
  • - `, - ); - } - - render() { - if (!this.menu) { - return html``; - } - - if (this.menuItems) { - this.links = this.menuItems; - } - - if (this.menu === 'web') { - return html` `; - } - - if (this.menu === 'more') { - return html` - `; - } - - return html` -

    ${this.links.heading}

    - - - - `; - } } diff --git a/src/elements/ia-topnav/ia-topnav-more-slider.ts b/src/elements/ia-topnav/ia-topnav-more-slider.ts index 63276814..d1a21198 100644 --- a/src/elements/ia-topnav/ia-topnav-more-slider.ts +++ b/src/elements/ia-topnav/ia-topnav-more-slider.ts @@ -15,6 +15,28 @@ export class MoreSlider extends TrackedElement { @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; @property({ type: Array }) menuItems: IATopNavLink[] = []; + render() { + return html` +
      + ${this.menuItems.map( + (item) => + html`
    • + ${item.title} +
    • `, + )} +
    + `; + } + + analyticsEvent(title: string) { + return `${this.config.eventCategory}|NavMore${toSentenceCase(title)}`; + } + static get styles(): CSSResultGroup { return [ themeStyles, @@ -33,26 +55,4 @@ export class MoreSlider extends TrackedElement { `, ]; } - - analyticsEvent(title: string) { - return `${this.config.eventCategory}|NavMore${toSentenceCase(title)}`; - } - - render() { - return html` -
      - ${this.menuItems.map( - (item) => - html`
    • - ${item.title} -
    • `, - )} -
    - `; - } } diff --git a/src/elements/ia-topnav/ia-topnav-primary-nav.ts b/src/elements/ia-topnav/ia-topnav-primary-nav.ts index b419c7d7..a5b747b2 100644 --- a/src/elements/ia-topnav/ia-topnav-primary-nav.ts +++ b/src/elements/ia-topnav/ia-topnav-primary-nav.ts @@ -41,250 +41,510 @@ export class PrimaryNav extends TrackedElement { @query('button.user-menu') private userMenuButton?: HTMLButtonElement; @query('ia-topnav-login-button') private loginButton?: HTMLElement; - static get styles(): CSSResultGroup { - return [ - themeStyles, - css` - button:focus, - input:focus { - outline: none; - } - - nav { - position: relative; - display: flex; - height: 4rem; - grid-template-areas: 'hamburger empty heart search user'; - -ms-grid-columns: 4rem minmax(1rem, 100%) 4rem 4rem 4rem; - grid-template-columns: 4rem auto 4rem 4rem 4rem; - -ms-grid-rows: 100%; - grid-template-rows: 100%; - background: var(--primaryNavBg); - border-bottom: 1px solid var(--primaryNavBottomBorder); - } - - nav.hide-search { - grid-template-areas: 'hamburger empty heart user'; - -ms-grid-columns: 4rem minmax(1rem, 100%) 4rem 4rem; - grid-template-columns: 4rem auto 4rem 4rem; - } + updated(props: PropertyValues) { + if (props.has('currentTab')) { + // early return + if (!this.currentTab || Object.keys(this.currentTab).length === 0) + return nothing; - .right-side-section { - display: flex; - margin-left: auto; - user-select: none; - } - button { - background: none; - color: inherit; - border: none; - font: inherit; - cursor: pointer; - } + const isUserMenuTab = + this.currentTab && this.currentTab.mediatype === 'usermenu'; + if (isUserMenuTab) { + const mediaButtons = Array.from( + this.shadowRoot + ?.querySelector('ia-topnav-media-menu') + ?.shadowRoot?.querySelectorAll('ia-topnav-media-button') ?? [], + ); + const lastMediaButton = mediaButtons.filter((element) => { + return element.shadowRoot + ?.querySelector('a') + ?.classList.contains('images'); + }); - .branding { - position: static; - float: left; - margin: 0 !important; - padding: 0 5px 0 10px; - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - transform: translate(0, 0); + let nextElement; + if (this.username) { + nextElement = this.shadowRoot?.querySelector('a.upload'); + } else { + nextElement = this.shadowRoot + ?.querySelector('ia-topnav-login-button') + ?.shadowRoot?.querySelector('span a'); } - slot, - .branding { - display: flex; - justify-content: left; - align-items: center; - } + const menuItemElement = + lastMediaButton[0]?.shadowRoot?.querySelector('a.menu-item'); - ia-topnav-media-menu { - flex: 1; - justify-self: stretch; - } + const focusElement = + this.currentTab.moveTo === 'next' ? nextElement : menuItemElement; - .ia-logo { - height: 3rem; - width: 2.7rem; - display: inline-block; - } - .ia-wordmark { - height: 3rem; - width: 9.5rem; + if (focusElement) { + (focusElement as HTMLElement).focus(); } - .ia-logo, - .ia-wordmark { - margin-right: 5px; + } else if (this.currentTab.moveTo === 'next') { + if (this.shadowRoot?.querySelector('.user-menu')) { + (this.shadowRoot?.querySelector('.user-menu') as HTMLElement).focus(); + } else { + ( + this.shadowRoot + ?.querySelector('ia-topnav-login-button') + ?.shadowRoot?.querySelectorAll('span a')[0] as HTMLElement + )?.focus(); } + } + } + } - .hamburger { - -ms-grid-row: 1; - -ms-grid-column: 1; - grid-area: hamburger; - padding: 0; - } - .hamburger svg { - height: 4rem; - width: 4rem; - fill: var(--activeColor); - } + render() { + // const mediaMenuTabIndex = this.openMenu === 'media' ? '' : '-1'; + return html` + + `; + } - .sr-only { - position: absolute; - width: 1px; - height: 1px; - margin: -1px; - padding: 0; - border: 0; - overflow: hidden; - white-space: nowrap; - clip: rect(1px, 1px, 1px, 1px); - -webkit-clip-path: inset(50%); - clip-path: inset(50%); - user-select: none; - } + /** Distance (px) from this element's right edge to the right edge of the account dropdown toggle. */ + getAccountDropdownOffset(): number { + const hostRect = this.getBoundingClientRect(); - .search-trigger { - padding: 0; - } - .search-trigger svg { - height: 4rem; - width: 4rem; - } - .search-trigger .fill-color { - fill: var(--iconFill); - } + if (this.userMenuButton) { + return hostRect.right - this.userMenuButton.getBoundingClientRect().right; + } - .search-container { - display: none; - } + if (this.loginButton) { + const loginRect = this.loginButton.getBoundingClientRect(); + const innerOffset = ( + this.loginButton as LoginButton + ).getDropdownToggleOffset(); + return hostRect.right - loginRect.right + innerOffset; + } - .search-container.open { - display: flex; - position: absolute; - top: 0; - right: 4rem; - bottom: 0; - left: 4rem; - z-index: 3; - padding: 0.5rem; - border-radius: 1rem 1rem 0 0; - background: var(--primaryNavBg); - align-items: center; - animation: fade-in 0.2s forwards; - } + return 0; + } - .search-container ::slotted(*) { - display: block; - } + toggleMediaMenu(e: Event) { + this.trackClick(e); + this.dispatchEvent( + new CustomEvent('menuToggled', { + detail: { + menuName: 'media', + }, + }), + ); + } - .search-container slot { - width: 100%; - } + toggleSearchMenu(e: Event) { + this.trackClick(e); + this.dispatchEvent( + new CustomEvent('menuToggled', { + detail: { + menuName: 'search', + }, + }), + ); + } - @keyframes fade-in { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } - } + toggleUserMenu(e: Event) { + this.trackClick(e); + this.dispatchEvent( + new CustomEvent('menuToggled', { + detail: { + menuName: 'user', + }, + }), + ); + } - .upload { - display: none; - } + get userIcon() { + const userMenuClass = this.openMenu === 'user' ? 'active' : ''; + const userMenuToolTip = + this.openMenu === 'user' ? 'Close user menu' : 'Expand user menu'; - .upload span { - display: none; - } + return html` + + `; + } - .upload svg { - height: 3rem; - width: 3rem; - } + get loginIcon() { + return html` + + `; + } - .screen-name { - display: none; - font-size: 1.3rem; - vertical-align: middle; - text-transform: uppercase; - } + get searchMenuOpen() { + return this.openMenu === 'search'; + } - .user-menu { - color: var(--lightTextColor); - padding: 0.5rem; - height: 100%; - } + get allowSecondaryIcon() { + return this.secondIdentitySlotMode === 'allow'; + } - button.user-menu:hover, - button.user-menu:focus { - color: var(--linkHoverColor); + /** + * The search slot container, rendered between ia-topnav-media-menu and + * right-side-section so it sits left of the Upload button on desktop. + */ + get searchSlotContainer() { + if (this.hideSearch) return nothing; + return html` +
    + +
    + `; + } + + get searchMenu() { + if (this.hideSearch) return nothing; + + return html` + + `; + } + + get mobileDonateHeart() { + return html` + + ${icons.donateUnpadded} + "Donate to the archive" + + `; + } + + get uploadButtonTemplate() { + return html` + ${icons.upload} + Upload + `; + } + + get userStateTemplate() { + return html``; + } + + get secondLogoSlot() { + return this.allowSecondaryIcon + ? html` + + + ` + : nothing; + } + + get secondLogoClass() { + return this.allowSecondaryIcon ? 'second-logo' : ''; + } + + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + button:focus, + input:focus { outline: none; } - .user-menu.active { - border-radius: 1rem 1rem 0 0; - background: var(--activeButtonBg); + nav { + position: relative; + display: flex; + height: 4rem; + grid-template-areas: 'hamburger empty heart search user'; + -ms-grid-columns: 4rem minmax(1rem, 100%) 4rem 4rem 4rem; + grid-template-columns: 4rem auto 4rem 4rem 4rem; + -ms-grid-rows: 100%; + grid-template-rows: 100%; + background: var(--primaryNavBg); + border-bottom: 1px solid var(--primaryNavBottomBorder); } - .user-menu img { - display: block; - width: 3rem; - height: 3rem; + nav.hide-search { + grid-template-areas: 'hamburger empty heart user'; + -ms-grid-columns: 4rem minmax(1rem, 100%) 4rem 4rem; + grid-template-columns: 4rem auto 4rem 4rem; } - .link-home { - text-decoration: none; - display: inline-flex; + .right-side-section { + display: flex; + margin-left: auto; + user-select: none; } - a.link-home:focus, - a.link-home:focus-visible { - outline-offset: 1px; + button { + background: none; + color: inherit; + border: none; + font: inherit; + cursor: pointer; } - @media only screen and (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) and (max-device-width: 905px) { - .branding.second-logo { - padding-right: 0; - } + .branding { + position: static; + float: left; + margin: 0 !important; + padding: 0 5px 0 10px; + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0); } - @media (min-width: 906px) { - .branding.second-logo { - padding-right: 20px; - } + slot, + .branding { + display: flex; + justify-content: left; + align-items: center; } - @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { - slot[name='opt-sec-logo'] { - display: none; - } + ia-topnav-media-menu { + flex: 1; + justify-self: stretch; + } - .right-side-section { - display: initial; - } - .right-side-section .user-info { - float: right; - } + .ia-logo { + height: 3rem; + width: 2.7rem; + display: inline-block; + } + .ia-wordmark { + height: 3rem; + width: 9.5rem; + } + .ia-logo, + .ia-wordmark { + margin-right: 5px; } - @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { - :host { - --userIconWidth: 3.2rem; - --userIconHeight: 3.2rem; - } + .hamburger { + -ms-grid-row: 1; + -ms-grid-column: 1; + grid-area: hamburger; + padding: 0; + } + .hamburger svg { + height: 4rem; + width: 4rem; + fill: var(--activeColor); + } + + .mobile-donate-link { + display: inline-block; + } + .mobile-donate-link svg { + height: 4rem; + width: 4rem; + } + .mobile-donate-link .fill-color { + fill: rgb(255, 0, 0); + } + + .sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + border: 0; + overflow: hidden; + white-space: nowrap; + clip: rect(1px, 1px, 1px, 1px); + -webkit-clip-path: inset(50%); + clip-path: inset(50%); + user-select: none; + } + + .search-trigger { + padding: 0; + } + .search-trigger svg { + height: 4rem; + width: 4rem; + } + .search-trigger .fill-color { + fill: var(--iconFill); + } + + .search-container { + display: none; + } + + .search-container.open { + display: flex; + position: absolute; + top: 0; + right: 4rem; + bottom: 0; + left: 4rem; + z-index: 3; + padding: 0.5rem; + border-radius: 1rem 1rem 0 0; + background: var(--primaryNavBg); + align-items: center; + animation: fade-in 0.2s forwards; + } + + .search-container ::slotted(*) { + display: block; + } + + .search-container slot { + width: 100%; + } + + @keyframes fade-in { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + + .upload { + display: none; + } + + .upload span { + display: none; + } + + .upload svg { + height: 3rem; + width: 3rem; + } + + .screen-name { + display: none; + font-size: 1.3rem; + vertical-align: middle; + text-transform: uppercase; + } + + .user-menu { + color: var(--lightTextColor); + padding: 0.5rem; + height: 100%; + } + + button.user-menu:hover, + button.user-menu:focus { + color: var(--linkHoverColor); + outline: none; + } + + .user-menu.active { + border-radius: 1rem 1rem 0 0; + background: var(--activeButtonBg); + } + + .user-menu img { + display: block; + width: 3rem; + height: 3rem; + } + + .link-home { + text-decoration: none; + display: inline-flex; + } + a.link-home:focus, + a.link-home:focus-visible { + outline-offset: 1px; + } + + @media only screen and (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) and (max-device-width: 905px) { + .branding.second-logo { + padding-right: 0; + } + } + + @media (min-width: 906px) { + .branding.second-logo { + padding-right: 20px; + } + } + + @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { + slot[name='opt-sec-logo'] { + display: none; + } + + .right-side-section { + display: initial; + } + .right-side-section .user-info { + float: right; + } + } + + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + :host { + --userIconWidth: 3.2rem; + --userIconHeight: 3.2rem; + } nav { display: flex; @@ -400,264 +660,4 @@ export class PrimaryNav extends TrackedElement { `, ]; } - - /** Distance (px) from this element's right edge to the right edge of the account dropdown toggle. */ - getAccountDropdownOffset(): number { - const hostRect = this.getBoundingClientRect(); - - if (this.userMenuButton) { - return hostRect.right - this.userMenuButton.getBoundingClientRect().right; - } - - if (this.loginButton) { - const loginRect = this.loginButton.getBoundingClientRect(); - const innerOffset = ( - this.loginButton as LoginButton - ).getDropdownToggleOffset(); - return hostRect.right - loginRect.right + innerOffset; - } - - return 0; - } - - toggleMediaMenu(e: Event) { - this.trackClick(e); - this.dispatchEvent( - new CustomEvent('menuToggled', { - detail: { - menuName: 'media', - }, - }), - ); - } - - toggleSearchMenu(e: Event) { - this.trackClick(e); - this.dispatchEvent( - new CustomEvent('menuToggled', { - detail: { - menuName: 'search', - }, - }), - ); - } - - toggleUserMenu(e: Event) { - this.trackClick(e); - this.dispatchEvent( - new CustomEvent('menuToggled', { - detail: { - menuName: 'user', - }, - }), - ); - } - - updated(props: PropertyValues) { - if (props.has('currentTab')) { - // early return - if (!this.currentTab || Object.keys(this.currentTab).length === 0) - return nothing; - - const isUserMenuTab = - this.currentTab && this.currentTab.mediatype === 'usermenu'; - if (isUserMenuTab) { - const mediaButtons = Array.from( - this.shadowRoot - ?.querySelector('ia-topnav-media-menu') - ?.shadowRoot?.querySelectorAll('ia-topnav-media-button') ?? [], - ); - const lastMediaButton = mediaButtons.filter((element) => { - return element.shadowRoot - ?.querySelector('a') - ?.classList.contains('images'); - }); - - let nextElement; - if (this.username) { - nextElement = this.shadowRoot?.querySelector('a.upload'); - } else { - nextElement = this.shadowRoot - ?.querySelector('ia-topnav-login-button') - ?.shadowRoot?.querySelector('span a'); - } - - const menuItemElement = - lastMediaButton[0]?.shadowRoot?.querySelector('a.menu-item'); - - const focusElement = - this.currentTab.moveTo === 'next' ? nextElement : menuItemElement; - - if (focusElement) { - (focusElement as HTMLElement).focus(); - } - } else if (this.currentTab.moveTo === 'next') { - if (this.shadowRoot?.querySelector('.user-menu')) { - (this.shadowRoot?.querySelector('.user-menu') as HTMLElement).focus(); - } else { - ( - this.shadowRoot - ?.querySelector('ia-topnav-login-button') - ?.shadowRoot?.querySelectorAll('span a')[0] as HTMLElement - )?.focus(); - } - } - } - } - - get userIcon() { - const userMenuClass = this.openMenu === 'user' ? 'active' : ''; - const userMenuToolTip = - this.openMenu === 'user' ? 'Close user menu' : 'Expand user menu'; - - return html` - - `; - } - - get loginIcon() { - return html` - - `; - } - - get searchMenuOpen() { - return this.openMenu === 'search'; - } - - get allowSecondaryIcon() { - return this.secondIdentitySlotMode === 'allow'; - } - - /** - * The search slot container, rendered between ia-topnav-media-menu and - * right-side-section so it sits left of the Upload button on desktop. - */ - get searchSlotContainer() { - if (this.hideSearch) return nothing; - return html` -
    - -
    - `; - } - - get searchMenu() { - if (this.hideSearch) return nothing; - - return html` - - `; - } - - get mobileDonateHeart() { - return html` - - ${icons.donateUnpadded} - "Donate to the archive" - - `; - } - - get uploadButtonTemplate() { - return html` - ${icons.upload} - Upload - `; - } - - get userStateTemplate() { - return html``; - } - - get secondLogoSlot() { - return this.allowSecondaryIcon - ? html` - - - ` - : nothing; - } - - get secondLogoClass() { - return this.allowSecondaryIcon ? 'second-logo' : ''; - } - - render() { - // const mediaMenuTabIndex = this.openMenu === 'media' ? '' : '-1'; - return html` - - `; - } } diff --git a/src/elements/ia-topnav/ia-topnav-save-page-form.ts b/src/elements/ia-topnav/ia-topnav-save-page-form.ts index e044a79d..5ba1392d 100644 --- a/src/elements/ia-topnav/ia-topnav-save-page-form.ts +++ b/src/elements/ia-topnav/ia-topnav-save-page-form.ts @@ -13,6 +13,54 @@ export class SavePageForm extends TrackedElement { @state() inputValid = true; + render() { + return html` +
    +

    Save Page Now

    +

    + Capture a web page as it appears now for use as a trusted citation in + the future. +

    +
    + + + +
    +

    Please enter a valid web address

    +
    + `; + } + + private validateURL(e: SubmitEvent) { + const target = e.target as HTMLFormElement; + const urlInput = target.querySelector( + '[name="url_preload"]', + ) as HTMLInputElement; + const valid = /\..{2,}$/.test(urlInput.value); + + if (!valid) { + e.preventDefault(); + this.inputValid = false; + return; + } + this.inputValid = true; + this.trackSubmit(e); + } + + get errorClass() { + return `error${this.inputValid ? '' : ' visible'}`; + } + static get styles(): CSSResultGroup { return [ themeStyles, @@ -71,52 +119,4 @@ export class SavePageForm extends TrackedElement { srOnlyStyles, ]; } - - private validateURL(e: SubmitEvent) { - const target = e.target as HTMLFormElement; - const urlInput = target.querySelector( - '[name="url_preload"]', - ) as HTMLInputElement; - const valid = /\..{2,}$/.test(urlInput.value); - - if (!valid) { - e.preventDefault(); - this.inputValid = false; - return; - } - this.inputValid = true; - this.trackSubmit(e); - } - - get errorClass() { - return `error${this.inputValid ? '' : ' visible'}`; - } - - render() { - return html` -
    -

    Save Page Now

    -

    - Capture a web page as it appears now for use as a trusted citation in - the future. -

    -
    - - - -
    -

    Please enter a valid web address

    -
    - `; - } } diff --git a/src/elements/ia-topnav/ia-topnav-wayback-slider.ts b/src/elements/ia-topnav/ia-topnav-wayback-slider.ts index b46c0a63..77ef0c86 100644 --- a/src/elements/ia-topnav/ia-topnav-wayback-slider.ts +++ b/src/elements/ia-topnav/ia-topnav-wayback-slider.ts @@ -24,38 +24,36 @@ export class WaybackSlider extends TrackedElement { @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig; @property({ type: Array }) mobileAppsLinks: IATopNavLink[] = []; - static get styles(): CSSResultGroup { - return [ - themeStyles, - subnavListCSS, - css` - @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { - :host { - display: block; - grid-column: 1 / 4; - padding: 0 1.5rem; - } - - h4 { - margin-top: 0; - font: normal 100 1.6rem var(--themeFontFamily); - } - - .grid { - display: grid; - grid-template-columns: minmax(auto, 260px) 1fr minmax(auto, 260px); - /* Possible for 890 - 935: minmax(auto, 260px) 1fr minmax(auto, 260px) */ - grid-column-gap: 2.5rem; - } - - .link-lists { - display: grid; - grid-template-columns: calc(50% - 1.25rem) calc(50% - 1.25rem); - grid-column-gap: 2.5rem; - } - } - `, - ]; + render() { + return html` +
    + + + +
    + `; } get mobileAppsItems() { @@ -92,35 +90,37 @@ export class WaybackSlider extends TrackedElement { return `${this.config?.eventCategory}|${toSentenceCase(title)}`; } - render() { - return html` -
    - - - -
    - `; + static get styles(): CSSResultGroup { + return [ + themeStyles, + subnavListCSS, + css` + @media (min-width: ${TOPNAV_MOBILE_BREAKPOINT}px) { + :host { + display: block; + grid-column: 1 / 4; + padding: 0 1.5rem; + } + + h4 { + margin-top: 0; + font: normal 100 1.6rem var(--themeFontFamily); + } + + .grid { + display: grid; + grid-template-columns: minmax(auto, 260px) 1fr minmax(auto, 260px); + /* Possible for 890 - 935: minmax(auto, 260px) 1fr minmax(auto, 260px) */ + grid-column-gap: 2.5rem; + } + + .link-lists { + display: grid; + grid-template-columns: calc(50% - 1.25rem) calc(50% - 1.25rem); + grid-column-gap: 2.5rem; + } + } + `, + ]; } } diff --git a/src/elements/ia-topnav/ia-topnav.ts b/src/elements/ia-topnav/ia-topnav.ts index 0880eb45..8e73d6a1 100644 --- a/src/elements/ia-topnav/ia-topnav.ts +++ b/src/elements/ia-topnav/ia-topnav.ts @@ -90,98 +90,16 @@ export class IATopNav extends LitElement { private boundHandleClick = this.handleDocumentClick.bind(this); - private get normalizedBaseHost() { - return !this.localLinks ? this.baseHost : ''; + connectedCallback() { + super.connectedCallback(); + document.addEventListener('keydown', this.boundHandleKeydown); + document.addEventListener('click', this.boundHandleClick); } - static get styles(): CSSResultGroup { - return [ - themeStyles, - css` - :host { - --white: #fff; - --grey13: #222; - --grey20: #333; - --grey40: #666; - --grey28: #474747; - --grey60: #999; - --grey66: #aaa; - --grey80: #ccc; - --greya0: #a0a0a0; - --grey6f: #6f6f6f; - --errorYellow: #ffcd27; - - --linkColor: #4b64ff; - --linkHoverColor: var(--white); - --subnavLinkColor: var(--grey66); - --primaryTextColor: var(--white); - --inverseTextColor: var(--grey20); - --lightTextColor: var(--grey60); - --activeColor: var(--white); - --activeButtonBg: var(--grey20); - --iconFill: var(--grey60); - --desktopSearchIconFill: var(--grey20); - - --mediaMenuBg: var(--grey13); - --mediaLabelDesktopColor: var(--grey60); - --activeDesktopMenuIcon: var(--grey28); - - --mediaSliderBg: var(--grey20); - --mediaSliderDesktopBg: var(--grey28); - - --primaryNavBg: var(--grey13); - --primaryNavBottomBorder: var(--grey20); - - --desktopSubnavBg: var(--grey20); - - --dropdownMenuBg: var(--grey20); - --dropdownMenuInfoItem: var(--greya0); - --dropdownMenuDivider: var(--grey40); - --inverseDropdownMenuInfoItem: var(--grey6f); - - --loginTextColor: var(--grey60); - - --themeFontFamily: 'Helvetica Neue', Helvetica, Arial, sans-serif; - --logoWidthTablet: 263px; - - --savePageSubmitBg: var(--grey13); - --savePageSubmitText: var(--white); - --savePageInputBorder: var(--grey60); - --savePageErrorText: var(--errorYellow); - - color: var(--primaryTextColor); - font-family: var(--themeFontFamily); - } - - ia-topnav-primary-nav:focus { - outline: none !important; - } - - #close-layer { - display: none; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 3; - } - #close-layer.visible { - display: block; - } - - .topnav { - position: relative; - z-index: 4; - } - - @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { - ia-topnav-desktop-subnav { - display: none; - } - } - `, - ]; + disconnectedCallback() { + super.disconnectedCallback(); + document.removeEventListener('keydown', this.boundHandleKeydown); + document.removeEventListener('click', this.boundHandleClick); } updated(props: PropertyValues) { @@ -198,16 +116,55 @@ export class IATopNav extends LitElement { } } - connectedCallback() { - super.connectedCallback(); - document.addEventListener('keydown', this.boundHandleKeydown); - document.addEventListener('click', this.boundHandleClick); + render() { + return html` +
    + + ${this.secondLogoSlot} ${this.searchSlot} + + + (this.currentTab = e.detail)} + > +
    + ${this.username ? this.userMenu : this.signedOutDropdown} + +
    + `; } - disconnectedCallback() { - super.disconnectedCallback(); - document.removeEventListener('keydown', this.boundHandleKeydown); - document.removeEventListener('click', this.boundHandleClick); + private get normalizedBaseHost() { + return !this.localLinks ? this.baseHost : ''; } private handleDocumentKeydown(e: KeyboardEvent) { @@ -404,50 +361,93 @@ export class IATopNav extends LitElement { return html``; } - render() { - return html` -
    - - ${this.secondLogoSlot} ${this.searchSlot} - - - (this.currentTab = e.detail)} - > -
    - ${this.username ? this.userMenu : this.signedOutDropdown} - -
    - `; + static get styles(): CSSResultGroup { + return [ + themeStyles, + css` + :host { + --white: #fff; + --grey13: #222; + --grey20: #333; + --grey40: #666; + --grey28: #474747; + --grey60: #999; + --grey66: #aaa; + --grey80: #ccc; + --greya0: #a0a0a0; + --grey6f: #6f6f6f; + --errorYellow: #ffcd27; + + --linkColor: #4b64ff; + --linkHoverColor: var(--white); + --subnavLinkColor: var(--grey66); + --primaryTextColor: var(--white); + --inverseTextColor: var(--grey20); + --lightTextColor: var(--grey60); + --activeColor: var(--white); + --activeButtonBg: var(--grey20); + --iconFill: var(--grey60); + --desktopSearchIconFill: var(--grey20); + + --mediaMenuBg: var(--grey13); + --mediaLabelDesktopColor: var(--grey60); + --activeDesktopMenuIcon: var(--grey28); + + --mediaSliderBg: var(--grey20); + --mediaSliderDesktopBg: var(--grey28); + + --primaryNavBg: var(--grey13); + --primaryNavBottomBorder: var(--grey20); + + --desktopSubnavBg: var(--grey20); + + --dropdownMenuBg: var(--grey20); + --dropdownMenuInfoItem: var(--greya0); + --dropdownMenuDivider: var(--grey40); + --inverseDropdownMenuInfoItem: var(--grey6f); + + --loginTextColor: var(--grey60); + + --themeFontFamily: 'Helvetica Neue', Helvetica, Arial, sans-serif; + --logoWidthTablet: 263px; + + --savePageSubmitBg: var(--grey13); + --savePageSubmitText: var(--white); + --savePageInputBorder: var(--grey60); + --savePageErrorText: var(--errorYellow); + + color: var(--primaryTextColor); + font-family: var(--themeFontFamily); + } + + ia-topnav-primary-nav:focus { + outline: none !important; + } + + #close-layer { + display: none; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 3; + } + #close-layer.visible { + display: block; + } + + .topnav { + position: relative; + z-index: 4; + } + + @media (max-width: ${TOPNAV_MOBILE_BREAKPOINT - 1}px) { + ia-topnav-desktop-subnav { + display: none; + } + } + `, + ]; } } From 325d366862ba55f53a9a29db3f7408da87e8b94a Mon Sep 17 00:00:00 2001 From: Jason Buckner Date: Wed, 30 Sep 2026 15:04:46 -0700 Subject: [PATCH 8/8] WEBDEV-9038: Address review on the topnav migration - Combine the small lib helpers into lib/helpers.ts with a test, and drop the unused makeBooleanFromString and the redundant query handler (the wayback search already defaults to the same one). - Add unit tests for the keyboard navigation. - Drop sr-only-styles. The hidden input labels become aria-labels and the mobile donate heart uses ia-sr-only-text. - Inline the desktop subnav and hamburger templates into render. - Build the menus in willUpdate so they're right on the first render. - Default buildTopNavMenus' userid to '' rather than a placeholder and fix its docs. - Tighten the tests Isa flagged and cover localLinks being set. - Add an archive.org font size toggle to the topnav demo. It's on when the topnav is the element being viewed. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HjwDQaR3hvZ8J2PP4117W2 --- src/elements/ia-topnav/data/menus.ts | 9 +- src/elements/ia-topnav/dropdown-menu.ts | 3 +- .../ia-topnav/ia-topnav-desktop-subnav.ts | 18 +- .../ia-topnav-icon-hamburger.test.ts | 11 +- .../ia-topnav/ia-topnav-icon-hamburger.ts | 8 +- .../ia-topnav/ia-topnav-login-button.ts | 3 +- .../ia-topnav/ia-topnav-media-button.test.ts | 5 +- .../ia-topnav/ia-topnav-media-button.ts | 2 +- .../ia-topnav/ia-topnav-media-menu.test.ts | 17 +- .../ia-topnav/ia-topnav-media-menu.ts | 2 +- .../ia-topnav/ia-topnav-media-subnav.ts | 3 +- .../ia-topnav/ia-topnav-more-slider.ts | 3 +- .../ia-topnav/ia-topnav-primary-nav.test.ts | 12 ++ .../ia-topnav/ia-topnav-primary-nav.ts | 20 +-- .../ia-topnav-save-page-form.test.ts | 9 + .../ia-topnav/ia-topnav-save-page-form.ts | 4 +- src/elements/ia-topnav/ia-topnav-story.ts | 58 +++++- .../ia-topnav/ia-topnav-user-menu.test.ts | 2 - .../ia-topnav/ia-topnav-wayback-search.ts | 4 +- .../ia-topnav/ia-topnav-wayback-slider.ts | 5 +- src/elements/ia-topnav/ia-topnav.test.ts | 101 +++++++++-- src/elements/ia-topnav/ia-topnav.ts | 2 +- src/elements/ia-topnav/lib/format-url.ts | 2 - src/elements/ia-topnav/lib/helpers.test.ts | 46 +++++ src/elements/ia-topnav/lib/helpers.ts | 25 +++ .../ia-topnav/lib/keyboard-navigation.test.ts | 169 ++++++++++++++++++ .../ia-topnav/lib/make-boolean-string.ts | 12 -- src/elements/ia-topnav/lib/query-handler.ts | 7 - src/elements/ia-topnav/lib/t-sentence-case.ts | 10 -- src/themes/sr-only-styles.ts | 24 --- 30 files changed, 446 insertions(+), 150 deletions(-) delete mode 100644 src/elements/ia-topnav/lib/format-url.ts create mode 100644 src/elements/ia-topnav/lib/helpers.test.ts create mode 100644 src/elements/ia-topnav/lib/helpers.ts create mode 100644 src/elements/ia-topnav/lib/keyboard-navigation.test.ts delete mode 100644 src/elements/ia-topnav/lib/make-boolean-string.ts delete mode 100644 src/elements/ia-topnav/lib/query-handler.ts delete mode 100644 src/elements/ia-topnav/lib/t-sentence-case.ts delete mode 100644 src/themes/sr-only-styles.ts diff --git a/src/elements/ia-topnav/data/menus.ts b/src/elements/ia-topnav/data/menus.ts index cc8721dd..0f0b204c 100644 --- a/src/elements/ia-topnav/data/menus.ts +++ b/src/elements/ia-topnav/data/menus.ts @@ -1,5 +1,3 @@ -// @see https://git.archive.org/www/offshoot/-/blob/main/guides/update-top-nav.md - import { IATopNavConfig, IATopNavMenuConfig } from '../models'; export const defaultTopNavConfig: IATopNavConfig = { @@ -12,15 +10,18 @@ export const defaultTopNavConfig: IATopNavConfig = { /** * Creates archive.org top navigation configuration * @param { string } userid archive.org account (immutable) userid - * @param { boolean } localLinks passing in false will ensure all links begin: https://archive.org + * @param { string } baseHost prefixed to every archive.org link. Pass '' for + * links relative to the current host. * @param { string } waybackPagesArchived label readable 'how many pages in WayBack machine?' * If you don't pass in something, you'll get the potentially * older/less accurate version. * @param { string } itemIdentifier The current item being viewed, to populate admin menu items + * @param { string } uploader email of the item's uploader, for the uploader admin section + * @param { string } biblio biblio URL for a texts item, for the biblio admin section * @returns { object } */ export function buildTopNavMenus( - userid: string = '___USERID___', + userid: string = '', baseHost: string = 'https://archive.org', waybackPagesArchived: string = '', itemIdentifier: string = '', diff --git a/src/elements/ia-topnav/dropdown-menu.ts b/src/elements/ia-topnav/dropdown-menu.ts index 3c3c0c29..ed83c7f0 100644 --- a/src/elements/ia-topnav/dropdown-menu.ts +++ b/src/elements/ia-topnav/dropdown-menu.ts @@ -10,8 +10,7 @@ import { property } from 'lit/decorators.js'; import icons from './assets/img/icons'; import { defaultTopNavConfig } from './data/menus'; -import formatUrl from './lib/format-url'; -import { makeBooleanString } from './lib/make-boolean-string'; +import { formatUrl, makeBooleanString } from './lib/helpers'; import { IATopNavConfig, IATopNavLink, diff --git a/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts b/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts index 0f2c0ba6..ccf38ab9 100644 --- a/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts +++ b/src/elements/ia-topnav/ia-topnav-desktop-subnav.ts @@ -1,10 +1,10 @@ -import { CSSResultGroup, TemplateResult, css, html, nothing } from 'lit'; +import { CSSResultGroup, TemplateResult, css, html } from 'lit'; import { property } from 'lit/decorators.js'; import { customElement } from '@src/util/custom-element'; import TrackedElement from './tracked-element'; import icons from './assets/img/icons'; -import formatUrl from './lib/format-url'; +import { formatUrl } from './lib/helpers'; import { IATopNavLink } from './models'; import themeStyles from '@src/themes/theme-styles'; @@ -16,14 +16,7 @@ export class DesktopSubnav extends TrackedElement { render() { return html`
      - ${this.listItems} -
    - `; - } - - get listItems() { - return this.menuItems - ? this.menuItems.map( + ${this.menuItems.map( (link) => html`
  • `, - ) - : nothing; + )} + + `; } static iconFor(title: string): TemplateResult { diff --git a/src/elements/ia-topnav/ia-topnav-icon-hamburger.test.ts b/src/elements/ia-topnav/ia-topnav-icon-hamburger.test.ts index ebe6ac62..c5b394ae 100644 --- a/src/elements/ia-topnav/ia-topnav-icon-hamburger.test.ts +++ b/src/elements/ia-topnav/ia-topnav-icon-hamburger.test.ts @@ -9,12 +9,19 @@ describe('', () => { const icon = await fixture( html``, ); + const titleId = () => + icon.shadowRoot?.querySelector('svg title')?.getAttribute('id'); + + expect(titleId()).to.equal('hamburgerTitleID'); icon.active = true; await icon.updateComplete; - const titleElement = icon.shadowRoot?.querySelector('svg title'); + expect(titleId()).to.match(/close/); + + icon.active = false; + await icon.updateComplete; - expect(titleElement?.getAttribute('id')).to.match(/close/); + expect(titleId()).to.equal('hamburgerTitleID'); }); }); diff --git a/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts b/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts index 0c6b4f03..6233ad1a 100644 --- a/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts +++ b/src/elements/ia-topnav/ia-topnav-icon-hamburger.ts @@ -6,10 +6,8 @@ import { customElement } from '@src/util/custom-element'; @customElement('ia-topnav-icon-hamburger') export class HamBurger extends Icon { render() { - return this.active ? HamBurger.opened : HamBurger.closed; - } + if (this.active) return icons.close; - static get closed() { return html` ', () => { '.menu-item', ) as HTMLAnchorElement; - setTimeout(() => link.click()); - const response = await oneEvent(el, 'mediaTypeSelected'); + const selected = oneEvent(el, 'mediaTypeSelected'); + link.click(); + const response = await selected; expect(response).to.exist; }); diff --git a/src/elements/ia-topnav/ia-topnav-media-button.ts b/src/elements/ia-topnav/ia-topnav-media-button.ts index 59a6a45c..43d958d4 100644 --- a/src/elements/ia-topnav/ia-topnav-media-button.ts +++ b/src/elements/ia-topnav/ia-topnav-media-button.ts @@ -1,7 +1,7 @@ import { CSSResultGroup, TemplateResult, css, html } from 'lit'; import TrackedElement from './tracked-element'; import icons from './assets/img/icons'; -import toSentenceCase from './lib/t-sentence-case'; +import { toSentenceCase } from './lib/helpers'; import { property } from 'lit/decorators.js'; import { customElement } from '@src/util/custom-element'; import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; diff --git a/src/elements/ia-topnav/ia-topnav-media-menu.test.ts b/src/elements/ia-topnav/ia-topnav-media-menu.test.ts index e8286edc..1bb330fe 100644 --- a/src/elements/ia-topnav/ia-topnav-media-menu.test.ts +++ b/src/elements/ia-topnav/ia-topnav-media-menu.test.ts @@ -29,16 +29,17 @@ describe('', () => { expect(textsButton).to.not.be.null; }); - test('renders with closed class if done animating', async () => { + test('renders closed until the media menu is opened', async () => { const mediaMenu = await fixture(component); + const container = () => + mediaMenu.shadowRoot?.querySelector('.media-menu-container'); - // mediaMenu.mediaMenuAnimate = true; - // await mediaMenu.updateComplete; + expect(container()?.classList.contains('closed')).to.be.true; - expect( - mediaMenu.shadowRoot - ?.querySelector('.media-menu-container') - ?.classList.contains('closed'), - ).to.be.true; + mediaMenu.openMenu = 'media'; + await mediaMenu.updateComplete; + + expect(container()?.classList.contains('open')).to.be.true; + expect(container()?.classList.contains('closed')).to.be.false; }); }); diff --git a/src/elements/ia-topnav/ia-topnav-media-menu.ts b/src/elements/ia-topnav/ia-topnav-media-menu.ts index 9a14bf83..8e982568 100644 --- a/src/elements/ia-topnav/ia-topnav-media-menu.ts +++ b/src/elements/ia-topnav/ia-topnav-media-menu.ts @@ -3,7 +3,7 @@ import { property, queryAll } from 'lit/decorators.js'; import { customElement } from '@src/util/custom-element'; import { defaultTopNavConfig } from './data/menus'; -import formatUrl from './lib/format-url'; +import { formatUrl } from './lib/helpers'; import './ia-topnav-media-button'; import { MediaButton } from './ia-topnav-media-button'; import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; diff --git a/src/elements/ia-topnav/ia-topnav-media-subnav.ts b/src/elements/ia-topnav/ia-topnav-media-subnav.ts index 6c8001c1..b2c98840 100644 --- a/src/elements/ia-topnav/ia-topnav-media-subnav.ts +++ b/src/elements/ia-topnav/ia-topnav-media-subnav.ts @@ -4,8 +4,7 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import TrackedElement from './tracked-element'; import './ia-topnav-wayback-slider'; import './ia-topnav-more-slider'; -import toSentenceCase from './lib/t-sentence-case'; -import formatUrl from './lib/format-url'; +import { formatUrl, toSentenceCase } from './lib/helpers'; import { property } from 'lit/decorators.js'; import { customElement } from '@src/util/custom-element'; import { diff --git a/src/elements/ia-topnav/ia-topnav-more-slider.ts b/src/elements/ia-topnav/ia-topnav-more-slider.ts index d1a21198..b0e8ac3f 100644 --- a/src/elements/ia-topnav/ia-topnav-more-slider.ts +++ b/src/elements/ia-topnav/ia-topnav-more-slider.ts @@ -3,8 +3,7 @@ import { property } from 'lit/decorators.js'; import { customElement } from '@src/util/custom-element'; import TrackedElement from './tracked-element'; -import toSentenceCase from './lib/t-sentence-case'; -import formatUrl from './lib/format-url'; +import { formatUrl, toSentenceCase } from './lib/helpers'; import { IATopNavConfig, IATopNavLink } from './models'; import { defaultTopNavConfig } from './data/menus'; import themeStyles from '@src/themes/theme-styles'; diff --git a/src/elements/ia-topnav/ia-topnav-primary-nav.test.ts b/src/elements/ia-topnav/ia-topnav-primary-nav.test.ts index 08d1233d..87e758e3 100644 --- a/src/elements/ia-topnav/ia-topnav-primary-nav.test.ts +++ b/src/elements/ia-topnav/ia-topnav-primary-nav.test.ts @@ -39,6 +39,18 @@ afterEach(() => { }); describe('', () => { + test('labels the mobile donate heart for screen readers', async () => { + const el = await fixture( + component({ baseHost: 'archive.org', username: '' }), + ); + const label = el.shadowRoot?.querySelector( + '.mobile-donate-link ia-sr-only-text', + ); + + expect(customElements.get('ia-sr-only-text')).to.exist; + expect(label?.textContent).to.contain('Donate to the archive'); + }); + test('renders the login link when no username present', async () => { const el = await fixture( component({ diff --git a/src/elements/ia-topnav/ia-topnav-primary-nav.ts b/src/elements/ia-topnav/ia-topnav-primary-nav.ts index a5b747b2..a28ad24d 100644 --- a/src/elements/ia-topnav/ia-topnav-primary-nav.ts +++ b/src/elements/ia-topnav/ia-topnav-primary-nav.ts @@ -5,8 +5,9 @@ import './ia-topnav-icon-hamburger'; import './ia-topnav-login-button'; import type { LoginButton } from './ia-topnav-login-button'; import './ia-topnav-media-menu'; +import '@src/elements/ia-sr-only-text/ia-sr-only-text'; import logoWordmarkStacked from './assets/img/wordmark-stacked'; -import formatUrl from './lib/format-url'; +import { formatUrl } from './lib/helpers'; import { property, query } from 'lit/decorators.js'; import { customElement } from '@src/util/custom-element'; import { @@ -266,7 +267,7 @@ export class PrimaryNav extends TrackedElement { )} > ${icons.donateUnpadded} - "Donate to the archive" + "Donate to the archive" `; } @@ -401,21 +402,6 @@ export class PrimaryNav extends TrackedElement { fill: rgb(255, 0, 0); } - .sr-only { - position: absolute; - width: 1px; - height: 1px; - margin: -1px; - padding: 0; - border: 0; - overflow: hidden; - white-space: nowrap; - clip: rect(1px, 1px, 1px, 1px); - -webkit-clip-path: inset(50%); - clip-path: inset(50%); - user-select: none; - } - .search-trigger { padding: 0; } diff --git a/src/elements/ia-topnav/ia-topnav-save-page-form.test.ts b/src/elements/ia-topnav/ia-topnav-save-page-form.test.ts index 95e50828..5e5156c1 100644 --- a/src/elements/ia-topnav/ia-topnav-save-page-form.test.ts +++ b/src/elements/ia-topnav/ia-topnav-save-page-form.test.ts @@ -23,6 +23,15 @@ async function submitWith(el: SavePageForm, url: string): Promise { } describe('', () => { + test('names the URL input for screen readers', async () => { + const el = await fixture(component); + const urlInput = el.shadowRoot?.querySelector('[name="url_preload"]'); + + expect(urlInput?.getAttribute('aria-label')).to.equal( + 'Enter a URL to save', + ); + }); + test('rejects a URL with no domain suffix and shows the error', async () => { const el = await fixture(component); diff --git a/src/elements/ia-topnav/ia-topnav-save-page-form.ts b/src/elements/ia-topnav/ia-topnav-save-page-form.ts index 5ba1392d..50be4d0e 100644 --- a/src/elements/ia-topnav/ia-topnav-save-page-form.ts +++ b/src/elements/ia-topnav/ia-topnav-save-page-form.ts @@ -5,7 +5,6 @@ import { customElement } from '@src/util/custom-element'; import { IATopNavConfig, TOPNAV_MOBILE_BREAKPOINT } from './models'; import { defaultTopNavConfig } from './data/menus'; import themeStyles from '@src/themes/theme-styles'; -import { srOnlyStyles } from '@src/themes/sr-only-styles'; @customElement('ia-topnav-save-page-form') export class SavePageForm extends TrackedElement { @@ -27,9 +26,9 @@ export class SavePageForm extends TrackedElement { the future.

    - [] = [ { @@ -50,9 +83,21 @@ export class IATopNavStory extends LitElement { this.lastEvent = `analyticsSubmit → ${e.detail?.event ?? ''}`; } + private restoreRootFontSize() { + if (this.rootFontSizeBefore === undefined) return; + document.documentElement.style.fontSize = this.rootFontSizeBefore; + this.rootFontSizeBefore = undefined; + } + private toggleRow( label: string, - key: 'signedIn' | 'onAnItem' | 'admin' | 'canManageFlags' | 'hideSearch', + key: + | 'signedIn' + | 'onAnItem' + | 'admin' + | 'canManageFlags' + | 'hideSearch' + | 'archiveFontSize', ) { return html` @@ -106,12 +151,18 @@ export class IATopNavStory extends LitElement { ${this.toggleRow('Admin on the item', 'admin')} ${this.toggleRow('Can manage flags', 'canManageFlags')} ${this.toggleRow('Hide search', 'hideSearch')} + ${this.toggleRow('archive.org font size', 'archiveFontSize')}

    The admin sections of the user menu need all three of Signed in, Viewing an item and Admin on the item. Narrow the window below 890px for the mobile layout.

    +

    + archive.org font size sets the page's root font size to 10px, which + the topnav is built for. It applies to the whole demo page, so it's + on by default only when the topnav is the element being viewed. +

    @@ -128,6 +179,11 @@ export class IATopNavStory extends LitElement { Setting uploader adds the uploader's account links, and biblio adds the book-scanning links for a texts item.

    +

    + Sizes are in rem and assume the host page sets + html { font-size: 10px }, as archive.org and offshoot + both do. +

    A search bar goes in the search slot. Offshoot slots an ia-dropdown-search-bar in there. diff --git a/src/elements/ia-topnav/ia-topnav-user-menu.test.ts b/src/elements/ia-topnav/ia-topnav-user-menu.test.ts index 1190194a..583d3bdd 100644 --- a/src/elements/ia-topnav/ia-topnav-user-menu.test.ts +++ b/src/elements/ia-topnav/ia-topnav-user-menu.test.ts @@ -22,8 +22,6 @@ describe('', () => { }); test('does not render admin links for logged in users', async () => { - // NOTE: top-nav never renders admin links now -- that's been delegated to dynamic JS insertion - // in petabox tree (since it's only relevant there). const el = await fixture(component2); el.menuItems = buildTopNavMenus('brewster_userid').user; diff --git a/src/elements/ia-topnav/ia-topnav-wayback-search.ts b/src/elements/ia-topnav/ia-topnav-wayback-search.ts index f31cd7e0..68d57ac2 100644 --- a/src/elements/ia-topnav/ia-topnav-wayback-search.ts +++ b/src/elements/ia-topnav/ia-topnav-wayback-search.ts @@ -6,7 +6,6 @@ import searchIcon from './assets/img/icon-search'; import logo from './assets/img/wayback-logo'; import { TOPNAV_MOBILE_BREAKPOINT } from './models'; import themeStyles from '@src/themes/theme-styles'; -import { srOnlyStyles } from '@src/themes/sr-only-styles'; /** * The Wayback Machine search form shown inside the topnav's wayback slider. @@ -49,9 +48,9 @@ export class IATopNavWaybackSearch extends LitElement { >${logo}

    -