diff --git a/client/src/containers/Header.js b/client/src/containers/Header.js index f9b94e192..e8866651a 100644 --- a/client/src/containers/Header.js +++ b/client/src/containers/Header.js @@ -1,5 +1,5 @@ import React from "react"; -import onClickOutside from 'react-onclickoutside' +import onClickOutside from "react-onclickoutside"; import { connect } from "react-redux"; import { withRouter } from "../hoc/withRouter"; import { Link } from "react-router-dom"; @@ -11,6 +11,7 @@ import PropTypes from "prop-types"; import { ProgressBar } from "react-loader-spinner"; import { svgFilter } from "../utils/svg"; import LeaderIcon from "../components/leaderboard/LeaderIcon"; +import parse from "html-react-parser"; class Header extends React.Component { constructor(props) { @@ -223,7 +224,7 @@ class Header extends React.Component { handleClickOutside = () => { this.closeDropdown(); - } + }; render() { let strings = loadTranslations(this.state.lang); @@ -240,18 +241,27 @@ class Header extends React.Component { ar: strings.arabic, tr: strings.turkish, }; - + const ddOpen = Boolean(this.state.multiDDOpen); return ( -
this.closeDropdown()}> -
+
this.closeDropdown()}> + {/*


+
*/} +
+
{parse(strings.ctfInfo)}
+ + +
+
    @@ -316,14 +326,14 @@ class Header extends React.Component {
{window.location.pathname === constants.PATH_ROOT && !!this.props.web3 && ( - this.toggleDropdownState()} - to={constants.PATH_LEADERBOARD}> -
- + this.toggleDropdownState()} + to={constants.PATH_LEADERBOARD} + > +
+
- )} { @@ -345,26 +355,29 @@ class Header extends React.Component { {strings.Networks}

- {Object.values(constants.NETWORKS_INGAME).map((network, index) => { - if (network && network.name !== "local") { - if (Number(network.id) === this.state.chainId) - return false; // filter out current network - return ( -
{ - e.preventDefault(); - this.changeNetwork(network); - }} - className="dropdown-pill" - > - - {network.name} - -
- ); + {Object.values(constants.NETWORKS_INGAME).map( + (network, index) => { + if (network && network.name !== "local") { + if (Number(network.id) === this.state.chainId) + return false; // filter out current network + return ( +
{ + e.preventDefault(); + this.changeNetwork(network); + }} + className="dropdown-pill" + > + + {network.name} + +
+ ); + } + return null; } - return null; - })} + )}
@@ -375,7 +388,8 @@ class Header extends React.Component {

{Object.keys(LANGUAGES_MAP).map((languageString, index) => ( -
{ this.changeLanguage(e, languageString); }} @@ -455,4 +469,6 @@ function mapDispatchToProps(dispatch) { ); } -export default withRouter(connect(mapStateToProps, mapDispatchToProps)(onClickOutside(Header))); +export default withRouter( + connect(mapStateToProps, mapDispatchToProps)(onClickOutside(Header)) +); diff --git a/client/src/containers/Help.js b/client/src/containers/Help.js index 198a41a32..53c9f48d1 100644 --- a/client/src/containers/Help.js +++ b/client/src/containers/Help.js @@ -11,7 +11,7 @@ class Help extends React.Component { let strings = loadTranslations(language); return ( -
+

Setup Metamask

diff --git a/client/src/containers/Leaderboard.js b/client/src/containers/Leaderboard.js index 333f0aab3..53b0b1f86 100644 --- a/client/src/containers/Leaderboard.js +++ b/client/src/containers/Leaderboard.js @@ -2,7 +2,7 @@ import "../styles/leaderboard.css"; import LeaderList from "../components/leaderboard/LeaderList"; import Headers from "../components/leaderboard/Headers"; import { useEffect, useState, useCallback } from "react"; -import ReactPaginate from 'react-paginate'; +import ReactPaginate from "react-paginate"; import Search from "../components/leaderboard/Search"; import { getNetworkNamefromId } from "../utils/ethutil"; import { NETWORKS } from "client/src/constants"; @@ -12,169 +12,177 @@ import { ALIAS_PATH, getLeaderboardPath } from "client/src/constants"; const playersPerPage = 20; -let aliases = {} +let aliases = {}; const fetchAliases = async () => { - try { - const response = await axios.get(ALIAS_PATH) - aliases = response.data - } catch (err) { - console.log("Failed to fetch aliases") - } -} - -fetchAliases() - -function Leaderboard() { - const [offset, setOffset] = useState(0); - const [playersWithRank, setPlayersWithRank] = useState([]) - const [searchResult, setSearchResult] = useState([]) - const [searchKeyword, setSearchKeyword] = useState('') - const [currentNetworkName, setCurrentNetworkName] = useState('') - - const pageCount = Math.ceil(searchResult.length / playersPerPage); - const endOffset = offset + playersPerPage; - const currentItems = searchResult.slice(offset, endOffset); - - const handleNetworkChange = useCallback(async (networkId) => { - if (!networkId) { - return; - } - const networkName = getNetworkNamefromId(Number(networkId)) - setCurrentNetworkName(networkName) - }, []) - - const initateCurrentlySelectedChain = useCallback(async () => { - const networkId = await window.ethereum.request({ method: 'eth_chainId' }) - handleNetworkChange(networkId) - }, [handleNetworkChange]) - - // During the initial render - useEffect(() => { - initateCurrentlySelectedChain() - }, [initateCurrentlySelectedChain]) - - useEffect(() => { - window.ethereum.on('networkChanged', handleNetworkChange) - return () => { - window.ethereum.removeListener('networkChanged', handleNetworkChange) - } - }, [handleNetworkChange]) - - const fetchAndUpdate = useCallback(async () => { - try { - if (!currentNetworkName) { - return; - } - const leaderboardNetworkName = getLeaderboardNetworkNameFromNetworkName(currentNetworkName) - const response = await axios.get(getLeaderboardPath(leaderboardNetworkName)) - const result = response.data - const playersWithRank = result.map(assignRank).filter(isScoreNonZero).map(assignAlias) - setPlayersWithRank(playersWithRank) - setSearchResult(playersWithRank) - } catch (err) { - console.log("Failed to fetch leaderboard") - } - }, [currentNetworkName]) - - // When network changes - useEffect(() => { - fetchAndUpdate() - }, [fetchAndUpdate]) - - const getLeaderboardNetworkNameFromNetworkName = (networkName) => { - const networks = Object.entries(NETWORKS) - const network = networks.find(network => network[1]?.name === networkName) - const leaderboardNetworkName = network[0].toLowerCase().split("_")[0] - return capitaliseFirstLetter(leaderboardNetworkName); + try { + const response = await axios.get(ALIAS_PATH); + aliases = response.data; + } catch (err) { + console.log("Failed to fetch aliases"); + } +}; + +fetchAliases(); + +function Leaderboard() { + const [offset, setOffset] = useState(0); + const [playersWithRank, setPlayersWithRank] = useState([]); + const [searchResult, setSearchResult] = useState([]); + const [searchKeyword, setSearchKeyword] = useState(""); + const [currentNetworkName, setCurrentNetworkName] = useState(""); + + const pageCount = Math.ceil(searchResult.length / playersPerPage); + const endOffset = offset + playersPerPage; + const currentItems = searchResult.slice(offset, endOffset); + + const handleNetworkChange = useCallback(async (networkId) => { + if (!networkId) { + return; } - - const handlePageClick = (event) => { - const newOffset = (event.selected * playersPerPage) % searchResult.length; - setOffset(newOffset); + const networkName = getNetworkNamefromId(Number(networkId)); + setCurrentNetworkName(networkName); + }, []); + + const initateCurrentlySelectedChain = useCallback(async () => { + const networkId = await window.ethereum.request({ method: "eth_chainId" }); + handleNetworkChange(networkId); + }, [handleNetworkChange]); + + // During the initial render + useEffect(() => { + initateCurrentlySelectedChain(); + }, [initateCurrentlySelectedChain]); + + useEffect(() => { + window.ethereum.on("networkChanged", handleNetworkChange); + return () => { + window.ethereum.removeListener("networkChanged", handleNetworkChange); }; - - const isKeywordMatching = (keyword) => (player) => { - keyword = keyword.toLowerCase() - return ( - player.player.toLowerCase().includes(keyword) || - player.alias.toLowerCase().includes(keyword) - ) - } + }, [handleNetworkChange]); - const updateSearchResult = (keyword) => { - if (keyword === "") { - setSearchResult(playersWithRank) - return; - } - setSearchKeyword(keyword) - const result = playersWithRank.filter(isKeywordMatching(keyword)) - setSearchResult(result) - setOffset(0) + const fetchAndUpdate = useCallback(async () => { + try { + if (!currentNetworkName) { + return; + } + const leaderboardNetworkName = + getLeaderboardNetworkNameFromNetworkName(currentNetworkName); + const response = await axios.get( + getLeaderboardPath(leaderboardNetworkName) + ); + const result = response.data; + const playersWithRank = result + .map(assignRank) + .filter(isScoreNonZero) + .map(assignAlias); + setPlayersWithRank(playersWithRank); + setSearchResult(playersWithRank); + } catch (err) { + console.log("Failed to fetch leaderboard"); } - + }, [currentNetworkName]); + + // When network changes + useEffect(() => { + fetchAndUpdate(); + }, [fetchAndUpdate]); + + const getLeaderboardNetworkNameFromNetworkName = (networkName) => { + const networks = Object.entries(NETWORKS); + const network = networks.find( + (network) => network[1]?.name === networkName + ); + const leaderboardNetworkName = network[0].toLowerCase().split("_")[0]; + return capitaliseFirstLetter(leaderboardNetworkName); + }; + + const handlePageClick = (event) => { + const newOffset = (event.selected * playersPerPage) % searchResult.length; + setOffset(newOffset); + }; + + const isKeywordMatching = (keyword) => (player) => { + keyword = keyword.toLowerCase(); return ( -
-
-
-
Leaderboard
- -
- -
- -
-
- -
-
-
-
- ) + player.player.toLowerCase().includes(keyword) || + player.alias.toLowerCase().includes(keyword) + ); + }; + + const updateSearchResult = (keyword) => { + if (keyword === "") { + setSearchResult(playersWithRank); + return; + } + setSearchKeyword(keyword); + const result = playersWithRank.filter(isKeywordMatching(keyword)); + setSearchResult(result); + setOffset(0); + }; + + return ( +
+
+
+
Leaderboard
+ +
+ +
+ +
+
+ +
+
+
+
+ ); } const reactPaginateProps = { - pageRangeDisplayed: 5, - renderOnZeroPageCount:null, - breakLabel:"...", - nextLabel: , - previousLabel: , - containerClassName:"leaderboard-pagination-container", - pageLinkClassName:"leaderboard-pagination-page-item", - activeLinkClassName:"leaderboard-pagination-selected-page-item", - nextLinkClassName:"leaderboard-button-link", - previousLinkClassName:"leaderboard-button-link" -} - -const assignRank = ((item, index) => { - return { - ...item, - rank:index+1 - } -}) + pageRangeDisplayed: 5, + renderOnZeroPageCount: null, + breakLabel: "...", + nextLabel: , + previousLabel: , + containerClassName: "leaderboard-pagination-container", + pageLinkClassName: "leaderboard-pagination-page-item", + activeLinkClassName: "leaderboard-pagination-selected-page-item", + nextLinkClassName: "leaderboard-button-link", + previousLinkClassName: "leaderboard-button-link", +}; + +const assignRank = (item, index) => { + return { + ...item, + rank: index + 1, + }; +}; const assignAlias = (player) => { - const alias = aliases[player.player.toLowerCase()] - if(!alias) return player - return { - ...player, - alias:alias - } -} - -const isScoreNonZero = (player) => { - return player.score !== 0 -} - -const capitaliseFirstLetter = (string) => { - return string.charAt(0).toUpperCase() + string.slice(1) -} - -export default Leaderboard; \ No newline at end of file + const alias = aliases[player.player.toLowerCase()]; + if (!alias) return player; + return { + ...player, + alias: alias, + }; +}; + +const isScoreNonZero = (player) => { + return player.score !== 0; +}; + +const capitaliseFirstLetter = (string) => { + return string.charAt(0).toUpperCase() + string.slice(1); +}; + +export default Leaderboard; diff --git a/client/src/containers/Level.js b/client/src/containers/Level.js index 108cb9ebb..9a95914e5 100644 --- a/client/src/containers/Level.js +++ b/client/src/containers/Level.js @@ -150,9 +150,8 @@ class Level extends React.Component { const nextLevelId = findNextLevelId(this.props.level, this.props.levels); return ( -
-
-
+
+
{(isDescriptionMissingTranslation || isCompleteDescriptionMissingTranslation) && (
diff --git a/client/src/containers/Stats.js b/client/src/containers/Stats.js index eb3ce24c9..47f318047 100644 --- a/client/src/containers/Stats.js +++ b/client/src/containers/Stats.js @@ -102,7 +102,7 @@ class Stats extends React.Component { } render() { - return
+ return
diff --git a/client/src/gamedata/ar/strings.json b/client/src/gamedata/ar/strings.json index ad27ead90..c0c93b70c 100644 --- a/client/src/gamedata/ar/strings.json +++ b/client/src/gamedata/ar/strings.json @@ -2,6 +2,8 @@ "ethernaut": "ايثرناوت", "title": "الايثرناوت", "hiring": "نقوم بالتوظيف!", + "ctfRegister": "سجل الان!", + "ctfInfo": "نحن نستضيف Ethernaut CTF: حدث التقاط العلم لمدة 48 ساعة مع جوائز وتحديات blockchain، بدءًا من 16/03.", "info": "

لعبة ايثرناوت هي لعبة حرب تستند إلى ويب3 / سوليديتى مستوحاة من overthewire.org ، يتم لعبها في آلة إيثريوم اﻻفتراضية. كل مستوى هو عقد ذكي يحتاج إلى اختراق. اللعبة مفتوحة المصدر بنسبة 100٪ وجميع المستويات مساهمات من لاعبين آخرين. هل لديك فكرة شيقة؟ العلاقات العامة

", "home": "الرئيسية", "help": "مساعدة", diff --git a/client/src/gamedata/en/strings.json b/client/src/gamedata/en/strings.json index 9e88ffc24..62ac0036d 100644 --- a/client/src/gamedata/en/strings.json +++ b/client/src/gamedata/en/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "The Ethernaut", "hiring": "We're hiring!", + "ctfRegister": "Register now!", + "ctfInfo": "We are hosting Ethernaut CTF: A 48-hour capture the flag event with prizes and blockchain challenges, starting 16/03.", "info": "

The Ethernaut is a Web3/Solidity based wargame inspired by overthewire.org, played in the Ethereum Virtual Machine. Each level is a smart contract that needs to be 'hacked'. The game is 100% open source and all levels are contributions made by other players. Do you have an interesting idea? PRs are

", "home": "Home", "help": "Help", diff --git a/client/src/gamedata/es/strings.json b/client/src/gamedata/es/strings.json index d4a9ac7c0..21b703a3f 100644 --- a/client/src/gamedata/es/strings.json +++ b/client/src/gamedata/es/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "The Ethernaut", "hiring": "Contratamos", + "ctfRegister": "Regístrate!", + "ctfInfo": "Estamos organizando Ethernaut CTF: un evento de captura de la bandera de 48 horas con premios y desafíos blockchain, a partir del 16/03.", "info": "

The Ethernaut es un juego basado en Web3/Solidity inspirado por overthewire.org, funcionando en la Ethereum Virtual Machine. Cada nivel es un smart contract que el jugador necesita hackear. El juego es 100% de código abierto y todos los niveles son contribuciones hechas por otros jugadores. ¿Tienes una idea interesante? Cualquier sugerencia es

", "home": "Inicio", "help": "Ayuda", diff --git a/client/src/gamedata/fr/strings.json b/client/src/gamedata/fr/strings.json index 46dd98165..4aeb6b941 100644 --- a/client/src/gamedata/fr/strings.json +++ b/client/src/gamedata/fr/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "The Ethernaut", "hiring": "Nous embauchons!", + "ctfRegister": "S'inscrire maintenant!", + "ctfInfo": "Nous organisons Ethernaut CTF: Un événement de capture du drapeau de 48 heures avec des prix et des défis blockchain, à partir du 16/03.", "info": "

L'Ethernaut est un Wargame basé sur web3 / Solidity inspiré par overthewire.org , joué dans leMachine virtuelle Ethereum.Chaque niveau est un contrat intelligent qui doit être «piraté».Le jeu est 100% open source et tous les niveaux sont des contributions apportées par d'autres joueurs.Avez-vous une idée intéressante?Les PRS sont

", "home": "Accueil", "help": "Aide", diff --git a/client/src/gamedata/ja/strings.json b/client/src/gamedata/ja/strings.json index d27e5030a..445e27e92 100644 --- a/client/src/gamedata/ja/strings.json +++ b/client/src/gamedata/ja/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "The Ethernaut", "hiring": "We're hiring!", + "ctfRegister": "今すぐ登録!", + "ctfInfo": "私たちは Ethernaut CTF を主催しています: 賞品とブロックチェーン チャレンジを備えた 48 時間のキャプチャ ザ フラッグ イベントが 2003 年 16 月から始まります。", "info": "

Ethernautはoverthewire.orgにインスパイアされたEthereum仮想マシン(EVM)を使用するWeb3/Solidityハッキングゲームです。各レベルのスマートコントラクトは脆弱性のあるスマートコントラクトです。

このゲームは100%オープンソースでプレーヤーによって全てのレベルが作成されています。もし新たにゲームのアイデアがあれば

", "home": "ホーム", "help": "ヘルプ", diff --git a/client/src/gamedata/pt_br/strings.json b/client/src/gamedata/pt_br/strings.json index 8ee16baa9..334c8337d 100644 --- a/client/src/gamedata/pt_br/strings.json +++ b/client/src/gamedata/pt_br/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "Ethernaut", "hiring": "Estamos contratando!", + "ctfRegister": "Registrar agora!", + "ctfInfo": "Estamos hospedando o Ethernaut CTF: Um evento de captura da bandeira de 48 horas com prêmios e desafios de blockchain, começando em 16/03.", "info": "

O Ethernaut é um jogo baseado em Web3/Solidity inspirado no overthewire.org, jogado na Ethereum Virtual Machine. Cada nível é um contrato inteligente que precisa ser 'hackeado'. O jogo é 100% de código aberto e todos os níveis são contribuições feitas por outros jogadores. Você tem uma ideia interessante? PRs são

", "home": "Home", "help": "Ajuda", diff --git a/client/src/gamedata/ru/strings.json b/client/src/gamedata/ru/strings.json index 6d5090516..81b02c101 100644 --- a/client/src/gamedata/ru/strings.json +++ b/client/src/gamedata/ru/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "Ethernaut", "hiring": "Мы нанимаем", + "ctfRegister": "Зарегистрироваться!", + "ctfInfo": "Мы проводим Ethernaut CTF: 48-часовое мероприятие «Захват флага» с призами и испытаниями на блокчейне, которое начнется 16 марта.", "info": "

Ethernaut это Web3/Solidity варгейм на базе Ethereum Virtual Machine, вдохновленный overthewire.org. Каждый уровень является смарт-контрактом, который необходимо 'взломать'. Исходный код игры полностью открытый, а все уровни созданы другими игроками. У тебя есть интересная идея для нового уровня? !

", "home": "Назад", "help": "Помощь", diff --git a/client/src/gamedata/tr/strings.json b/client/src/gamedata/tr/strings.json index c36356f29..4f4be2981 100644 --- a/client/src/gamedata/tr/strings.json +++ b/client/src/gamedata/tr/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "The Ethernaut", "hiring": "İşe alıyoruz!", + "ctfRegister": "Şimdi üye Ol!", + "ctfInfo": "Ethernaut CTF'ye ev sahipliği yapıyoruz: 16/03'ten itibaren, ödüller ve blockchain mücadelelerinin yer aldığı 48 saatlik bir bayrak yakalama etkinliği.", "info": "

Ethernaut, esinlenerek Web3/Solidity tabanlı bir savaş oyunudur. overthewire.org, Ethereum sanal makinesinde oynandı.Her seviye, 'saldırıya uğraması' gereken akıllı bir sözleşmedir.Oyun% 100 açık kaynak ve tüm seviyeler diğer oyuncular tarafından yapılan katkılardır.İlginç bir fikrin var mı?PR'ler

", "home": "Anasayfa", "help": "Yardım", diff --git a/client/src/gamedata/zh_cn/strings.json b/client/src/gamedata/zh_cn/strings.json index cff160734..c4f5fe700 100644 --- a/client/src/gamedata/zh_cn/strings.json +++ b/client/src/gamedata/zh_cn/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "The Ethernaut", "hiring": "我们在招聘!", + "ctfRegister": "现在注册!", + "ctfInfo": "我们将举办 Ethernaut CTF: 为期 48 小时的夺旗活动,包含奖品和区块链挑战,将于 16 月 3 日开始。", "info": "

Ethernaut 是一个基于 Web3/Solidity 的对抗游戏,受 overthewire.org 启发, 运行于以太坊虚拟机. 每个关卡是一个需要被 'hacked' 的智能合约.

整个游戏百分百开源,并且由不同玩家贡献. 如果你也有有意思的想法?

", "home": "主页", "help": "帮助", diff --git a/client/src/gamedata/zh_tw/strings.json b/client/src/gamedata/zh_tw/strings.json index d7e3f36ec..7292d5700 100644 --- a/client/src/gamedata/zh_tw/strings.json +++ b/client/src/gamedata/zh_tw/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "The Ethernaut", "hiring": "我們正在招聘!", + "ctfRegister": "现在注册!", + "ctfInfo": "我们将举办 Ethernaut CTF: 为期 48 小时的夺旗活动,包含奖品和区块链挑战,将于 16 月 3 日开始。", "info": "

以太網是一個基於Web3/固體的戰爭遊戲,靈感來自overthewire.org, 在以太坊虛擬機中播放。每個級別都是需要“黑客”的智能合同。該遊戲是100%開源的,所有級別都是其他玩家做出的貢獻。你有一個有趣的主意嗎?PR是

", "home": "主頁", "help": "幫助", diff --git a/client/src/styles/app.css b/client/src/styles/app.css index dcd777063..1bc810aa4 100644 --- a/client/src/styles/app.css +++ b/client/src/styles/app.css @@ -114,13 +114,6 @@ hr { margin-top: 10px; } -.top { - border: none; - border-top: 1px solid var(--secondary-color); - height: 1px; - align-items: center; -} - h2 { font-size: 14px; padding: 1% 10% 0% 10%; @@ -149,6 +142,38 @@ button :hover { background-color: var(--primary-color); } +.header-container { + display: flex; + flex-direction: column; +} + +.top { + border: none; + border-top: 1px solid var(--secondary-color); + height: 1px; + align-items: center; +} + + +.top-banner { + display: flex; + gap: 10%; + align-items: center; + justify-content: space-between; + width: 100%; + height: 80px; + border-radius: 6px; + border: 2px solid var(--secondary-color); + margin-bottom: 4%; + margin-top: 2%; + padding: 2% +} + +.top-banner-text { + display: block; + overflow-wrap: break-word; +} + header { display: flex; justify-content: space-between; @@ -157,7 +182,7 @@ header { } .header-ul { - padding: 4px 0px; + padding: 0px 0px; margin-bottom: 0; } @@ -171,13 +196,12 @@ nav li { .nav-links { display: inline-block; - padding: 4px; + padding: 0px; } .nav-links a { color: var(--secondary-color); text-decoration: none; - padding-right: 5px; font-family: helvetica, sans-serif; } @@ -312,6 +336,13 @@ nav li { margin-top: 1%; } +.main-wrapper { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; +} + .game { display: flex; flex-wrap: wrap; @@ -522,7 +553,7 @@ footer { /* --------- styles for multi dropdowns --------------*/ .multi-dropdown{ - padding: 4px 9px; + padding: 0% 0px; } .multi-dropdown__icon{ @@ -698,6 +729,24 @@ footer { .appcontainer{ width: 100vw; } + + .top-banner-text { + font-size: smaller; + } + + .header-container { + align-items: center; + } + + .top-banner { + height: 100px; + width: 95%; + } + + .multi-dropdown{ + padding: 4px 9px; + } + .header-ul{ display: flex; margin-right: 20px;