From 813d3421bb994816e3db81b5a2905e2f27a61ad6 Mon Sep 17 00:00:00 2001 From: flashwave Date: Sat, 28 Aug 2021 17:06:14 +0000 Subject: [PATCH] Landing page redesign. --- assets/css/misuzu/_msz.css | 2 +- assets/css/misuzu/footer.css | 1 + assets/css/misuzu/header.css | 1 - assets/css/misuzu/home/landingv2-footer.css | 84 ++++++ assets/css/misuzu/home/landingv2-header.css | 91 ++++++ assets/css/misuzu/home/landingv2.css | 211 +++++++++++++ docs/contact.md | 4 +- docs/rules.md | 2 +- public/images/landing-logo.png | Bin 0 -> 33139 bytes src/Http/Handlers/HomeHandler.php | 156 ++++++---- templates/500.html | 2 +- templates/503.html | 2 +- templates/_layout/footer.twig | 2 - templates/_layout/header.twig | 98 ------ templates/home/home.twig | 128 ++++++++ templates/home/index.twig | 1 - templates/home/landing.twig | 316 ++++++++++++-------- templates/master.twig | 102 +++++++ 18 files changed, 911 insertions(+), 292 deletions(-) create mode 100644 assets/css/misuzu/home/landingv2-footer.css create mode 100644 assets/css/misuzu/home/landingv2-header.css create mode 100644 assets/css/misuzu/home/landingv2.css create mode 100644 public/images/landing-logo.png create mode 100644 templates/home/home.twig delete mode 100644 templates/home/index.twig diff --git a/assets/css/misuzu/_msz.css b/assets/css/misuzu/_msz.css index 1c753248..afe7f675 100644 --- a/assets/css/misuzu/_msz.css +++ b/assets/css/misuzu/_msz.css @@ -21,7 +21,7 @@ body { :root { --font-size: 12px; --line-height: 20px; - --font-regular: Tahoma, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif; + --font-regular: Verdana, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif; --font-monospace: Consolas, 'Liberation Mono', Menlo, Courier, monospace; --site-max-width: 1200px; diff --git a/assets/css/misuzu/footer.css b/assets/css/misuzu/footer.css index 6c4d1548..79360e95 100644 --- a/assets/css/misuzu/footer.css +++ b/assets/css/misuzu/footer.css @@ -5,6 +5,7 @@ color: inherit; text-decoration: none; } +.footer__link:focus, .footer__link:hover { text-decoration: underline; } diff --git a/assets/css/misuzu/header.css b/assets/css/misuzu/header.css index d96878f2..cdfe59f1 100644 --- a/assets/css/misuzu/header.css +++ b/assets/css/misuzu/header.css @@ -55,7 +55,6 @@ .header__desktop__link:focus { background-color: rgba(255, 255, 255, .2); } - .header__desktop__link:active { background-color: rgba(255, 255, 255, .1); } diff --git a/assets/css/misuzu/home/landingv2-footer.css b/assets/css/misuzu/home/landingv2-footer.css new file mode 100644 index 00000000..f9590fe4 --- /dev/null +++ b/assets/css/misuzu/home/landingv2-footer.css @@ -0,0 +1,84 @@ +.landingv2-footer { + flex: 0 0 auto; + --footer-background-mask-image: linear-gradient(180deg, transparent, var(--background-colour) 30px); + margin-top: 4px; + padding-top: 20px; +} +.landingv2-footer-background { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + mask-image: var(--footer-background-mask-image); + -webkit-mask-image: var(--footer-background-mask-image); + background: var(--background-pattern); + background-color: var(--header-accent-colour); + background-blend-mode: multiply; +} +.landingv2-footer-wrapper { + max-width: var(--site-max-width); + margin: 0 auto; + padding: 1em 4px; + display: grid; + grid-template-columns: repeat(2, 1fr); +} + +.landingv2-footer-navigation {} +.landingv2-footer-navigation a { + display: inline-block; + color: inherit; + text-decoration: none; + min-width: 200px; + cursor: pointer; + border-radius: 2px; + padding: 4px 10px; + margin: 1px 0; + transition: background-color .2s; +} +.landingv2-footer-navigation a:hover, +.landingv2-footer-navigation a:focus { + background-color: rgba(255, 255, 255, .2); +} +.landingv2-footer-navigation a:active { + background-color: rgba(255, 255, 255, .1); +} + +.landingv2-footer-copyright { + text-align: right; + line-height: 1.8em; + font-size: .9em; + align-self: flex-end; +} + +.landingv2-footer-copyright a { + color: inherit; + text-decoration: none; +} +.landingv2-footer-copyright a:focus, +.landingv2-footer-copyright a:hover { + text-decoration: underline; +} + +@media(max-width: 800px) { + .landingv2-footer-wrapper { + grid-template-columns: 1fr; + } + + .landingv2-footer-navigation { + text-align: center; + margin: 0 8px; + } + .landingv2-footer-navigation div { + display: inline-block; + } + .landingv2-footer-navigation a { + text-align: center; + min-width: 100px; + margin: 2px; + } + + .landingv2-footer-copyright { + text-align: center; + } +} diff --git a/assets/css/misuzu/home/landingv2-header.css b/assets/css/misuzu/home/landingv2-header.css new file mode 100644 index 00000000..81fd084c --- /dev/null +++ b/assets/css/misuzu/home/landingv2-header.css @@ -0,0 +1,91 @@ +.landingv2-header { + flex: 0 0 auto; + --header-background-mask-image: linear-gradient(0deg, transparent, var(--background-colour) 100px); + padding-bottom: 100px; +} +.landingv2-header-background { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: var(--background-pattern); + background-color: var(--header-accent-colour); + background-blend-mode: multiply; + mask-image: var(--header-background-mask-image); + -webkit-mask-image: var(--header-background-mask-image); +} +.landingv2-header-content { + margin: 0 auto; + max-width: 800px; +} + +.landingv2-welcome { + text-align: center; + margin: 10px; +} +.landingv2-welcome a { + color: inherit; + text-decoration: none; +} +.landingv2-welcome img { + max-width: 100%; + max-height: 100%; + vertical-align: middle; +} + +.landingv2-header-menu { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-gap: 4px; + padding: 0 4px; +} + +.landingv2-header-menu-link { + color: #fff; + text-decoration: none; + cursor: pointer; + border-radius: 2px; + background-color: var(--background-colour); + border: 1px solid var(--header-accent-colour); + transition: background-color .2s; + display: flex; + align-items: center; + min-height: 70px; + font-size: 1.4em; + padding: 10px 16px; + grid-column: 1; +} +.landingv2-header-menu-link:hover, +.landingv2-header-menu-link:focus { + background-color: var(--accent-colour); +} + +.landingv2-auth-link { + font-size: 2em; + justify-content: center; + text-align: center; + grid-column: 2; +} +.landingv2-auth-link-login { + grid-row: 1 / span 2; +} + +@media(max-width: 700px) { + .landingv2-header-menu { + grid-template-columns: 1fr; + } + + .landingv2-auth-link { + grid-column: 1; + } + + .landingv2-auth-link-login { + grid-row: 1; + min-height: 100px; + } + + .landingv2-auth-link-register { + grid-row: 2; + } +} diff --git a/assets/css/misuzu/home/landingv2.css b/assets/css/misuzu/home/landingv2.css new file mode 100644 index 00000000..19ac07ab --- /dev/null +++ b/assets/css/misuzu/home/landingv2.css @@ -0,0 +1,211 @@ +.landingv2-content { + padding: 0 4px; +} + +.landingv2-stats { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 40px; + margin: 40px; +} + +.landingv2-stat { + display: flex; + align-items: center; + margin: 10px; + text-shadow: 0 1px 4px #000; +} +.landingv2-stat-icon { + font-size: 4em; +} +.landingv2-stat-value { + font-size: 2em; + text-align: right; + flex: 1 1 auto; +} +.landingv2-stat-value-num { + font-weight: 700; +} + +.landingv2-forum { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-gap: 2px; + margin: 4px 0; +} + +.landingv2-forum-topics { + background-color: var(--container-colour); + box-shadow: 0 1px 2px #0009; + text-shadow: 0 1px 4px #000; + overflow: hidden; + word-wrap: break-word; +} +.landingv2-forum-topics-list { + display: flex; + flex-direction: column; + margin: 5px; + overflow: hidden; +} + +.landingv2-forum-topic { + border-radius: 2px; + background-color: rgba(17, 17, 17, .6); + transition: background-color .2s, box-shadow .2s, opacity .2s; +} +.landingv2-forum-topic:nth-child(even) { + background-color: rgba(25, 25, 25, .6); +} +.landingv2-forum-topic:hover, +.landingv2-forum-topic:focus { + background-color: rgba(34, 34, 34, .6); + box-shadow: 0 1px 4px #222; +} +.landingv2-forum-topic:not(:last-child) { + margin-bottom: 4px; +} + +.landingv2-forum-topic-link { + display: block; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + color: inherit; + text-decoration: none; + z-index: 200; +} + +.landingv2-forum-topic-info { + z-index: 100; + display: flex; + padding: 5px; + align-items: center; + min-height: 40px; + pointer-events: none; +} +.landingv2-forum-topic-info-icon { + flex: 0 0 auto; + border-radius: 2px; + width: 30px; + height: 30px; + margin-right: 4px; + background-color: var(--accent-colour); + background-size: 60px 60px; + background-image: radial-gradient(ellipse at center, rgba(255, 255, 255, .2) 0%, rgba(0, 0, 0, .4) 100%); + box-shadow: 0 1px 4px #111; + font-size: 1.5em; + line-height: 1.5em; + color: #fff; + display: flex; + justify-content: center; + align-items: center; + padding: 1px 1px 0 2px; +} + +.landingv2-forum-topic-info-details { + margin: 0 4px; + flex: 1 1 auto; + display: flex; + justify-content: center; + flex-direction: column; + line-height: 1.6em; + overflow: hidden; +} +.landingv2-forum-topic-info-details-title { + font-size: 1.3em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.landingv2-forum-topic-info-stats { + font-size: .9em; + display: flex; + flex: 0 0 auto; + text-align: center; + min-width: 60px; + flex-direction: column; +} +.landingv2-forum-topic-info-stats-posts, +.landingv2-forum-topic-info-stats-views { + font-size: .9em; + line-height: 1.3em; + opacity: .7; + pointer-events: auto; + cursor: default; +} +.landingv2-forum-topic-info-stats-posts { + font-size: 1.4em; + opacity: 1; +} + +.landingv2-news { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 2px; +} + +.landingv2-news-post { + background-color: var(--container-colour); + box-shadow: 0 1px 2px #0009; + text-shadow: 0 1px 4px #000; + overflow: hidden; + word-wrap: break-word; + padding: 0 10px 10px 10px; + display: flex; + flex-direction: column; +} +.landingv2-news-post p { + flex: 1 1 auto; +} +.landingv2-news-post-options { + text-align: right; +} + +.landingv2-online { + background-color: var(--container-colour); + box-shadow: 0 1px 2px #0009; + text-shadow: 0 1px 4px #000; + margin: 4px 0; +} +.landingv2-online-users { + scrollbar-width: thin; + overflow: auto; +} +.landingv2-online-inner { + display: flex; + padding: 2px; +} +.landingv2-online-avatar { + margin: 2px; + display: block; + flex: 0 0 auto; +} + +@media(max-width: 1100px) { + .landingv2-stat { + margin: 0; + } +} + +@media(max-width: 1024px) { + .landingv2-stats { + grid-template-columns: repeat(2, 1fr); + margin: 20px; + } +} + +@media(max-width: 900px) { + .landingv2-forum, + .landingv2-news { + grid-template-columns: 1fr; + } +} + +@media(max-width: 700px) { + .landingv2-stats { + grid-template-columns: 1fr; + } +} diff --git a/docs/contact.md b/docs/contact.md index 90c05c49..1937dab2 100644 --- a/docs/contact.md +++ b/docs/contact.md @@ -3,14 +3,14 @@ If you need to reach us outside of this website, this is the page for you. Below are a few ways of contact. ## E-mail - - [flash](mailto:me+flashii@flash.moe): Site Administrator + - [flash](mailto:flashii@flash.moe): Site Administrator ## Twitter - [@flashiinet](https://twitter.com/flashiinet): General updates and conversation. + - [@flashiistatus](https://twitter.com/flashiistatus): Exclusively system status updates, posts by this accounts are generally retweeted by @flashiinet. - [@smugwave](https://twitter.com/smugwave): Twitter of the owner, proceed with caution! ## Source Code - [Misuzu](https://github.com/flashwave/misuzu): Backend of the [website](https://flashii.net). - [Sharp Chat](https://github.com/flashii/sharp-chat): Chat Server software. - - [Kuroko](https://github.com/flashii/kuroko): Chat web client hosted at [chat.flashii.net](https://chat.flashii.net). - [Backup Manager](https://github.com/flashii/backup-manager): Program that runs every day at 12:00am UTC to back up any user generated content. diff --git a/docs/rules.md b/docs/rules.md index 719b281a..1e2d1293 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -27,7 +27,7 @@ Exceptions may be granted for bot accounts. There is a time and place for it, but Flashii is intended to be a footloose and fancy-free community. Moderator intervention will be used for petty shouting matches. -1. **You must be at least 13 years of age on the Gregorian calendar.** +1. **You must be at least 18 years of age on the Gregorian calendar.** When validating this a staff member will always ask this in a direct message, never in public channels. 1. **Link shorteners are not allowed.** diff --git a/public/images/landing-logo.png b/public/images/landing-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..134757e5ce30f5d0b7293598633365977aa26d3b GIT binary patch literal 33139 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
}@7kwM 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 `98ATrDh~~-#y^4MzW3oYn^mS%=%Y}uF)YWKI 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 QQ1GRxs;5$;WE1xP0sEkzz5oCK literal 0 HcmV?d00001 diff --git a/src/Http/Handlers/HomeHandler.php b/src/Http/Handlers/HomeHandler.php index 50706bfc..7660ae2a 100644 --- a/src/Http/Handlers/HomeHandler.php +++ b/src/Http/Handlers/HomeHandler.php @@ -13,76 +13,130 @@ use Misuzu\Users\UserSession; final class HomeHandler extends Handler { public function index(HttpResponse $response, HttpRequest $request): void { - if(Config::get('social.embed_linked', Config::TYPE_BOOL)) { - $linkedData = [ + if(UserSession::hasCurrent()) + $this->home($response, $request); + else + $this->landing($response, $request); + } + + public function landing(HttpResponse $response, HttpRequest $request): void { + $linkedData = Config::get('social.embed_linked', Config::TYPE_BOOL) + ? [ 'name' => Config::get('site.name', Config::TYPE_STR, 'Misuzu'), 'url' => Config::get('site.url', Config::TYPE_STR), 'logo' => Config::get('site.ext_logo', Config::TYPE_STR), 'same_as' => Config::get('social.linked', Config::TYPE_ARR), - ]; + ] : null; + + + $featuredNews = NewsPost::all(new Pagination(3), true); + + $stats = DB::query( + 'SELECT' + . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_deleted` IS NULL) AS `count_users_all`,' + . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)) AS `count_users_online`,' + . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 24 HOUR)) AS `count_users_active`,' + . ' (SELECT COUNT(`comment_id`) FROM `msz_comments_posts` WHERE `comment_deleted` IS NULL) AS `count_comments`,' + . ' (SELECT COUNT(`topic_id`) FROM `msz_forum_topics` WHERE `topic_deleted` IS NULL) AS `count_forum_topics`,' + . ' (SELECT COUNT(`post_id`) FROM `msz_forum_posts` WHERE `post_deleted` IS NULL) AS `count_forum_posts`' + )->fetch(); + + $onlineUsers = DB::query( + 'SELECT u.`user_id`, u.`username`, COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`' + . ' FROM `msz_users` AS u' + . ' LEFT JOIN `msz_roles` AS r' + . ' ON r.`role_id` = u.`display_role`' + . ' WHERE u.`user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)' + . ' ORDER BY u.`user_active` DESC, RAND()' + . ' LIMIT 100' + )->fetchAll(); + + // TODO: don't hardcode forum ids + $featuredForums = Config::get('landing.forum_categories', Config::TYPE_ARR); + + $popularTopics = []; + $activeTopics = []; + + if(!empty($featuredForums)) { + $getPopularTopics = DB::prepare( + 'SELECT t.`topic_id`, c.`forum_id`, t.`topic_title`, c.`forum_icon`, t.`topic_count_views`' + . ', (SELECT COUNT(*) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL) AS `topic_count_posts`' + . ' FROM `msz_forum_topics` AS t' + . ' LEFT JOIN `msz_forum_categories` AS c ON c.`forum_id` = t.`forum_id`' + . ' WHERE c.`forum_id` IN (' . implode(',', $featuredForums) . ') AND `topic_deleted` IS NULL AND `topic_locked` IS NULL' + . ' ORDER BY (SELECT COUNT(*) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL AND `post_created` > NOW() - INTERVAL 3 MONTH) DESC' + )->stmt; + $getPopularTopics->execute(); + for($i = 0; $i < 10; ++$i) { + $topicInfo = $getPopularTopics->fetchObject(); + if(empty($topicInfo)) + break; + $popularTopics[] = $topicInfo; + } + + $getActiveTopics = DB::prepare( + 'SELECT t.`topic_id`, c.`forum_id`, t.`topic_title`, c.`forum_icon`, t.`topic_count_views`' + . ', (SELECT COUNT(*) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL) AS `topic_count_posts`' + . ', (SELECT MAX(`post_id`) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL) AS `latest_post_id`' + . ' FROM `msz_forum_topics` AS t' + . ' LEFT JOIN `msz_forum_categories` AS c ON c.`forum_id` = t.`forum_id`' + . ' WHERE c.`forum_id` IN (' . implode(',', $featuredForums) . ') AND `topic_deleted` IS NULL AND `topic_locked` IS NULL' + . ' ORDER BY `topic_bumped` DESC' + )->stmt; + $getActiveTopics->execute(); + for($i = 0; $i < 10; ++$i) { + $topicInfo = $getActiveTopics->fetchObject(); + if(empty($topicInfo)) + break; + $activeTopics[] = $topicInfo; + } } + $response->setTemplate('home.landing', [ + 'statistics' => $stats, + 'online_users' => $onlineUsers, + 'featured_news' => $featuredNews, + 'linked_data' => $linkedData, + 'forum_popular' => $popularTopics, + 'forum_active' => $activeTopics, + ]); + } + + public function home(HttpResponse $response, HttpRequest $request): void { $featuredNews = NewsPost::all(new Pagination(5), true); - $stats = DB::query(' - SELECT - ( - SELECT COUNT(`user_id`) - FROM `msz_users` - WHERE `user_deleted` IS NULL - ) AS `count_users_all`, - ( - SELECT COUNT(`user_id`) - FROM `msz_users` - WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE) - ) AS `count_users_online`, - ( - SELECT COUNT(`user_id`) - FROM `msz_users` - WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 24 HOUR) - ) AS `count_users_active`, - ( - SELECT COUNT(`comment_id`) - FROM `msz_comments_posts` - WHERE `comment_deleted` IS NULL - ) AS `count_comments`, - ( - SELECT COUNT(`topic_id`) - FROM `msz_forum_topics` - WHERE `topic_deleted` IS NULL - ) AS `count_forum_topics`, - ( - SELECT COUNT(`post_id`) - FROM `msz_forum_posts` - WHERE `post_deleted` IS NULL - ) AS `count_forum_posts` - ')->fetch(); + $stats = DB::query( + 'SELECT' + . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_deleted` IS NULL) AS `count_users_all`,' + . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)) AS `count_users_online`,' + . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 24 HOUR)) AS `count_users_active`,' + . ' (SELECT COUNT(`comment_id`) FROM `msz_comments_posts` WHERE `comment_deleted` IS NULL) AS `count_comments`,' + . ' (SELECT COUNT(`topic_id`) FROM `msz_forum_topics` WHERE `topic_deleted` IS NULL) AS `count_forum_topics`,' + . ' (SELECT COUNT(`post_id`) FROM `msz_forum_posts` WHERE `post_deleted` IS NULL) AS `count_forum_posts`' + )->fetch(); $changelog = ChangelogChange::all(new Pagination(10)); - $birthdays = !UserSession::hasCurrent() ? [] : User::byBirthdate(); - $latestUser = !empty($birthdays) ? null : User::byLatest(); + $birthdays = User::byBirthdate(); + $latestUser = !empty($birthdays) ? null : User::byLatest(); - $onlineUsers = DB::query(' - SELECT - u.`user_id`, u.`username`, - COALESCE(u.`user_colour`, r.`role_colour`) as `user_colour` - FROM `msz_users` as u - LEFT JOIN `msz_roles` as r - ON r.`role_id` = u.`display_role` - WHERE u.`user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE) - ORDER BY u.`user_active` DESC - LIMIT 104 - ')->fetchAll(); + $onlineUsers = DB::query( + 'SELECT u.`user_id`, u.`username`, COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`' + . ' FROM `msz_users` AS u' + . ' LEFT JOIN `msz_roles` AS r' + . ' ON r.`role_id` = u.`display_role`' + . ' WHERE u.`user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)' + . ' ORDER BY u.`user_active` DESC, RAND()' + . ' LIMIT 104' + )->fetchAll(); - $response->setTemplate('home.landing', [ + $response->setTemplate('home.home', [ 'statistics' => $stats, 'latest_user' => $latestUser, 'online_users' => $onlineUsers, 'birthdays' => $birthdays, 'featured_changelog' => $changelog, 'featured_news' => $featuredNews, - 'linked_data' => $linkedData ?? null, ]); } } diff --git a/templates/500.html b/templates/500.html index 42abc0ec..9b8fc0bb 100644 --- a/templates/500.html +++ b/templates/500.html @@ -5,7 +5,7 @@ Error 500 diff --git a/templates/503.html b/templates/503.html index bfd8df66..32f2489d 100644 --- a/templates/503.html +++ b/templates/503.html @@ -5,7 +5,7 @@ Error 503 diff --git a/templates/_layout/footer.twig b/templates/_layout/footer.twig index 9424438c..a2a4aad6 100644 --- a/templates/_layout/footer.twig +++ b/templates/_layout/footer.twig @@ -2,8 +2,6 @@