commit 7e07d4d7f2171dee6b6f84adbb51fc85f0ed02f8
parent 4bb5de0d09251f81e3ce9bd20e8b61fc644967e8
Author: Katja (ctucx) <git@ctu.cx>
Date: Thu, 23 Jan 2025 11:26:00 +0100
parent 4bb5de0d09251f81e3ce9bd20e8b61fc644967e8
Author: Katja (ctucx) <git@ctu.cx>
Date: Thu, 23 Jan 2025 11:26:00 +0100
big stylesheet and template refactoring
10 files changed, 250 insertions(+), 339 deletions(-)
M
|
484
+++++++++++++++++++++++++++++++++----------------------------------------------
diff --git a/src/departuresView.js b/src/departuresView.js @@ -11,15 +11,14 @@ const departuresTemplate = (data, profile) => { let changes = 0; let lastArrival; - //<a class="reload icon-reload" title="${t("reload")}" @click=${() => refreshJourneyView(data.refreshToken, profile)}>${t("reload")}</a> return html` - <div class="departures"> + <div class="departuresView column"> <header> <a id="back" class="icon-back hidden" title="${t('back')}" @click=${() => history.back()}>${t('back')}</a> <div class="content"> <h3>Departures from ${data.name}</h3> </div> - <a class="icon-reload hidden">${t("reload")}</a> + <a id="reload" class="icon-reload invisible" title="${t("reload")}">${t("reload")}</a> </header> <div class="card"> @@ -39,7 +38,7 @@ const departuresTemplate = (data, profile) => { ${departure.cancelled ? html` <td><span class="cancelled-text">${t('cancelled-ride')}</span></td> ` : html` - <td><span>${platformTemplate(departure)}</span></td> + <td>${platformTemplate(departure)}</td> `} </tr> `)}
diff --git a/src/journeyView.js b/src/journeyView.js @@ -28,14 +28,14 @@ const legTemplate = (leg, profile) => { <thead> <tr> <td colspan="4"> - <span><a href="#/t/${profile}/${leg.tripId}">${lineDisplayName(leg.line)}${leg.direction ? html` → ${leg.direction}` : ''}</a> + <div class="center"><a href="#/t/${profile}/${leg.tripId}">${lineDisplayName(leg.line)}${leg.direction ? html` → ${leg.direction}` : ''}</a> ${leg.cancelled ? html`<b class="cancelled-text">${t('cancelled-ride')}</b>` : ''} - ${Object.entries(remarks).map(remarksTemplate)}</span> + ${Object.entries(remarks).map(remarksTemplate)}</div> </td> </tr> <tr> <td colspan="4"> - <div class="train-details"> + <div class="train-details center"> ${lineAdditionalName(leg.line) ? html` <div> Trip: ${lineAdditionalName(leg.line)} @@ -119,7 +119,7 @@ const journeyTemplate = (data, profile) => { } return html` - <div class="journey"> + <div class="journeyView column"> <header> ${data.slug ? html` <a class="icon-back" href="#/${data.slug}/${settings.journeysViewMode}" title="${t('back')}">${t('back')}</a>
diff --git a/src/journeysView.js b/src/journeysView.js @@ -8,7 +8,7 @@ import { html, render } from 'lit-html'; import { showAlertModal, showLoader, hideOverlay } from './overlays.js'; const journeysTemplate = (data) => html` - <div class="journeys"> + <div class="journeysView column"> <header id="header"> <a class="icon-back" href="#/" title="${t('back')}">${t('back')}</a> <div class="content"> @@ -35,7 +35,7 @@ const journeysTemplate = (data) => html` ` : ''} ${settings.journeysViewMode === 'table' ? html` ${data.earlierRef ? html` - <a class="loadMore icon-arrow2 flipped" title="${t('label_earlier')}" @click=${() => moreJourneys(data.slug, 'earlier')}></a> + <a class="arrowButton flipped icon-arrow2" title="${t('label_earlier')}" @click=${() => moreJourneys(data.slug, 'earlier')}></a> ` : ''} <div class="card"> @@ -58,7 +58,7 @@ const journeysTemplate = (data) => html` </div> ${data.laterRef ? html` - <a class="loadMore icon-arrow2" title="${t('label_later')}" @click=${() => moreJourneys(data.slug, 'later')}></a> + <a class="arrowButton icon-arrow2" title="${t('label_later')}" @click=${() => moreJourneys(data.slug, 'later')}></a> ` : ''} ` : ''} </div> @@ -99,16 +99,16 @@ const journeyOverviewTemplate = (profile, entry, slug, key) => { return html` <tr @click=${() => go(`/j/${profile}/${entry.refreshToken}`)}> - <td class="${cancelled ? 'cancelled' : ''}"><span>${timeTemplate(firstLeg, 'departure')}</span></td> + <td class="${cancelled ? 'cancelled' : ''}">${timeTemplate(firstLeg, 'departure')}</td> ${cancelled ? html` <td><span class="cancelled-text">${t('cancelled-ride')}</span></td> ` : html` - <td><span>${timeTemplate(lastLeg, 'arrival')}</span></td> + <td>${timeTemplate(lastLeg, 'arrival')}</td> `} - <td class="${cancelled ? 'cancelled' : ''}" title="${changesDuration > 0 ? 'including '+formatDuration(changesDuration)+' transfer durations' : ''}"><span>${formatDuration(duration)}</span></td> - <td><span>${changes-1}</span></td> - <td><span>${productsString}</span></td> - ${settings.showPrices ? html`<td><span>${formatPrice(entry.price)}</span></td>` : ''} + <td class="${cancelled ? 'cancelled' : ''}" title="${changesDuration > 0 ? 'including '+formatDuration(changesDuration)+' transfer durations' : ''}">${formatDuration(duration)}</td> + <td>${changes-1}</td> + <td>${productsString}</td> + ${settings.showPrices ? html`<td>${formatPrice(entry.price)}</td>` : ''} <td><a class="icon-arrow1"></a></td> </tr>`; };
diff --git a/src/overlays.js b/src/overlays.js @@ -5,11 +5,9 @@ export const showAlertModal = (text) => { showDiv('overlay'); return new Promise(resolve => { render(html` - <div class="modal"> - <div class="box alert"> - ${text} - <br><button class="color" @click=${() => { hideOverlay(); resolve(); }}>OK</button> - </div> + <div class="modal alert"> + ${text} + <br><button class="color" @click=${() => { hideOverlay(); resolve(); }}>OK</button> </div> `, ElementById('overlay')); }); @@ -19,13 +17,11 @@ export const showSelectModal = (items) => { showDiv('overlay'); return new Promise(resolve => { render(html` - <div class="modal"> - <div class="box select"> - ${items.map( - (item) => html`<a class="button color" @click=${item.action}>${item.label}</a>` - )} - <a class="button color" @click=${() => { hideOverlay(); resolve(); }}>Close</a> - </div> + <div class="modal select column"> + ${items.map( + (item) => html`<a class="button color" @click=${item.action}>${item.label}</a>` + )} + <a class="button color" @click=${() => { hideOverlay(); resolve(); }}>Close</a> </div> `, ElementById('overlay')); }); @@ -35,14 +31,12 @@ export const showModal = (title, content) => { showDiv('overlay'); return new Promise(resolve => { render(html` - <div class="modal"> - <div class="box dialog"> - <div class="header"> - <h4>${title}</h4> - <div class="close" title="Close" @click=${() => { hideOverlay(); resolve(); }}></div> - </div> - <div class="body">${content}</div> + <div class="modal dialog"> + <div class="header row"> + <h4>${title}</h4> + <div class="icon-close" title="Close" @click=${() => { hideOverlay(); resolve(); }}></div> </div> + <div class="body">${content}</div> </div> `, ElementById('overlay')); });
diff --git a/src/searchView.js b/src/searchView.js @@ -60,12 +60,12 @@ const iconFor = id => { }; const searchTemplate = (journeysHistory) => html` - <div id="searchView"> - <div class="title"> + <div class="searchView"> + <div class="title center"> <div class="icon-logo"></div> <h1>TrainSearch</h1> </div> - <form onsubmit="return false;"> + <form class="column" onsubmit="return false;"> <div class="row nowrap"> <label for="from">${t('from')}:</label> <input type="text" name="from" id="from" placeholder="${t('from')}" value="${fromValue}" autocomplete="off" @focus=${startTyping} @blur=${stopTyping} @keyup=${onKeyup} @keydown=${onKeydown} required> @@ -73,9 +73,10 @@ const searchTemplate = (journeysHistory) => html` </div> <div class="suggestions" id="fromSuggestions"></div> - <div class="row hidden" id="viaRow"> + <div class="row nowrap hidden" id="viaRow"> <label for="via">${t('via')}:</label> <input type="text" name="via" id="via" placeholder="${t('via')}" value="${viaValue}" autocomplete="off" @focus=${startTyping} @blur=${stopTyping} @keyup=${onKeyup} @keydown=${onKeydown} required> + <div class="button icon-arrow2 invisible"></div> </div> <div class="suggestions" id="viaSuggestions"></div> @@ -133,7 +134,7 @@ const searchTemplate = (journeysHistory) => html` </div> ${journeysHistory.length ? html` - <div id="historyButton" class="loadMore icon-arrow2" title="History" @click=${toggleHistory}></div> + <div id="historyButton" class="arrowButton icon-arrow2" title="History" @click=${toggleHistory}></div> ` : ''} </form>
diff --git a/src/settingsView.js b/src/settingsView.js @@ -12,7 +12,7 @@ export const showSettings = async () => { }; const settingsTemplate = () => html` - <div id="settingsView"> + <div class="settingsView"> <div class="row"> <label for="language">${t('language')}:</label> <select id="language">
diff --git a/src/templates.js b/src/templates.js @@ -26,7 +26,7 @@ export const remarksTemplate = ([type, remarks]) => !!remarks.length ? html` ` : ''; export const stopTemplate = (profile, stop) => { - return html`<a href="#/d/${profile}/${stop.id}">${stop.name} ${ds100Names(stop.id)}</a>`; + return html`<a class="center" href="#/d/${profile}/${stop.id}">${stop.name} ${ds100Names(stop.id)}</a>`; } export const platformTemplate = (data) => {
diff --git a/src/tripView.js b/src/tripView.js @@ -27,13 +27,13 @@ const tripTemplate = (data, profile) => { } return html` - <div class="journey"> + <div class="journeyView column"> <header> <a id="back" class="icon-back hidden" title="${t('back')}" @click=${() => history.back()}>${t('back')}</a> <div class="content"> <h3>Trip of ${lineDisplayName(data.line)} to ${data.direction}</h3> </div> - <a class="icon-reload hidden">${t("reload")}</a> + <a class="icon-reload invisible">${t("reload")}</a> </header> <div class="card"> @@ -41,18 +41,18 @@ const tripTemplate = (data, profile) => { <thead> <tr> <td colspan="4"> - <span>${bahnExpertUrl ? html` + <div class="center">${bahnExpertUrl ? html` <a href="${bahnExpertUrl}">${lineDisplayName(data.line)}${data.direction ? html` → ${data.direction}` : ''}</a> ` : html ` ${lineDisplayName(data.line)}${data.direction ? html` → ${data.direction}` : ''} `} ${data.cancelled ? html`<b class="cancelled-text">${t('cancelled-ride')}</b>` : ''} - ${Object.entries(remarks).map(remarksTemplate)}</span> + ${Object.entries(remarks).map(remarksTemplate)}</div> </td> </tr> <tr> <td colspan="4"> - <div class="train-details"> + <div class="train-details center"> ${lineAdditionalName(data.line) ? html` <div> Trip: ${lineAdditionalName(data.line)} @@ -77,17 +77,17 @@ const tripTemplate = (data, profile) => { <tr> <th>${t('arrival')}</th> <th>${t('departure')}</th> - <th class="station-">${t('station')}</th> + <th class="station">${t('station')}</th> <th>${t('platform')}</th> </tr> </thead> <tbody> ${(data.stopovers || []).map(stop => html` - <tr class="stop ${stop.cancelled ? 'cancelled' : ''}"> - <td><span>${timeTemplate(stop, 'arrival')}</span></td> - <td><span>${timeTemplate(stop, 'departure')}</span></td> - <td><span>${stopTemplate(profile, stop.stop)}</span></td> - <td><span>${platformTemplate(stop)}</span></td> + <tr class="${stop.cancelled ? 'cancelled' : ''}"> + <td>${timeTemplate(stop, 'arrival')}</td> + <td>${timeTemplate(stop, 'departure')}</td> + <td>${stopTemplate(profile, stop.stop)}</td> + <td>${platformTemplate(stop)}</td> </tr> `)} </tbody>
diff --git a/static/index.html b/static/index.html @@ -29,7 +29,6 @@ body { height: 100vh; width: 100vw; background-color: rgba(0, 0, 0, .7); - overflow: hidden; display: flex; } @@ -53,7 +52,7 @@ body { </style> </head> <body> - <div id="content"></div> + <div id="content" class="column"></div> <div id="overlay"> <noscript>JavaScript is required to use TrainSearch</noscript> <div id="logo">
diff --git a/static/style.css b/static/style.css @@ -15,13 +15,22 @@ html, body { overflow-x: hidden; overflow-y: visible; } + +#content { + min-height: 100vh; +} + +#overlay { + z-index: 1; + backdrop-filter: blur(10px); +} a { color: inherit; } -.pointer { - cursor: pointer; +.invisible { + visibility: hidden !important; } .hidden { @@ -38,13 +47,15 @@ a { flex-direction: row; } -.cancelled { - text-decoration-line: line-through; +.column { + display: flex; + flex-direction: column; } -.cancelled-text { - font-weight: bold; - color: red !important; +.center { + display: flex; + justify-content: center; + align-items: center; } .spinner { @@ -66,41 +77,13 @@ a { 100% { transform: rotate(360deg); } } -.loadMore { - cursor: pointer; - height: 72px; - width: 72px; - margin: 0 auto; - transition: transform 150ms; - user-select: none; - filter: invert(); -} - -.remarks { - /*background: #000000d0;*/ - padding: 0; - width: 100%; - margin: 0; - - td { - margin: 0 10px; - text-align: left; - display: block; - } - - span { - vertical-align: middle; - } -} - header { - position: relative; display: flex; flex-direction: row; justify-content: center; color: white; background-color: #222; - bottom-border: 1px solid rgba(255, 255, 255, .3); + border-bottom: 1px solid rgba(255, 255, 255, .3); h3 { margin-right: 1.5em; @@ -149,25 +132,80 @@ header { } -#content { - display: flex; - flex-direction: column; - min-height: 100vh; -} +.card { + overflow-x: auto; -#overlay { - position: fixed; - z-index: 1; - left: 0; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background-color: rgba(0,0,0,0.4); - backdrop-filter: blur(10px); + table { + border-bottom: 1px solid rgba(0, 0, 0, 0.3); + width: 100%; + background-color: #fff; + min-width: 390px; + max-width: 1000px; + } + + table a { + padding: 5px 3px; + text-decoration: none; + } + + thead { + .center { + padding: 5px 3px; + } + + tr:not(:last-child) { + background-color: #eee; + } + } + + tbody { + tr { + cursor: pointer; + border-top: 1px solid #ccc; + } + + tr:hover { + background-color: #ddd; + } + + tr:hover td { + background-color: transparent; + } + } + + td, th { + text-align: center; + overflow: hidden; + } + + th { + padding: 10px 5px; + } + + th.station { + width: 60%; + } + + .train-details { + flex-wrap: wrap; + padding: 0 !important; + + div { + margin: .4em 2em; + } + } + + .cancelled { + text-decoration-line: line-through; + } + + .cancelled-text { + font-weight: bold; + color: red !important; + } } -#settingsView { +.settingsView { .row { align-items: center; padding: 1em; @@ -175,6 +213,7 @@ header { } .row:last-child { + padding: .5em; border-bottom: unset; justify-content: right; } @@ -189,15 +228,11 @@ header { } } -#searchView { +.searchView { background-color: #222; flex-grow: 1; .title { - display: flex; - justify-content: center; - align-items: center; - .icon-logo { background-color: #7171e5; border-radius: 15%; @@ -223,18 +258,11 @@ header { form { color: white; - display: flex; - flex-direction: column; label[for=from], label[for=via], label[for=to], label[for=date], label[for=time] { display: none; } - table { - width: 100%; - color: black; - } - #time, #date { flex-grow: 1; } @@ -243,10 +271,6 @@ header { width: 100%; } - #via { - margin-right: 53px; - } - .button.icon-arrow1, .button.icon-arrow2, .button.icon-swap { @@ -286,28 +310,24 @@ header { overflow: visible; z-index: 999; height: 0; + width: 100%; - .box { - border-radius: 3px; - width: 100%; - - p { - font-size: 1.2em; - background-color: white; - color: black; - margin: 0; - border-top: 1px solid rgba(0, 0, 0, .2); - padding: .3em .6em; - cursor: pointer; - } + p { + font-size: 1.2em; + background-color: white; + color: black; + margin: 0; + border-top: 1px solid rgba(0, 0, 0, .2); + padding: .3em .6em; + cursor: pointer; + } - p:first-child { - border-top: 0px; - } + p:first-child { + border-top: 0px; + } - p:hover { - background-color: #d3d3d3; - } + p:hover { + background-color: #d3d3d3; } #selected { @@ -327,16 +347,14 @@ header { user-select: none; .row { - font-size: 1.2em; + justify-content: space-between; + cursor: pointer; + padding: .3em .6em .3em .3em; + margin: 0; background-color: white; color: black; - margin: 0; + font-size: 1.2em; border-top: 1px solid rgba(0, 0, 0, .2); - padding: .3em .6em .3em .3em; - cursor: pointer; - - display: flex; - justify-content: space-between; } :first-child { @@ -382,78 +400,19 @@ header { } } -.card { - overflow-x: auto; - - .train-details { - display: flex; - justify-content: center; - flex-wrap: wrap; - - div { - margin: .4em 2em; - } - } - - table { - border-bottom: 1px solid rgba(0, 0, 0, 0.3); - width: 100%; - background-color: #fff; - min-width: 390px; - max-width: 1000px; - } - - thead tr:not(:last-child) { - background-color: #eee; - } - - tbody { - tr { - border-top: 1px solid #ccc; - } - - tr:hover { - background-color: #ddd; - } - - tr:hover td { - background-color: transparent; - } - } - - tr { - background-color: #fff; - margin: 0 0 15px 0; - } - - td, th { - text-align: center; - overflow: hidden; - } - - th { - padding: 5px 3px; - } - - th.station { - width: 60%; - } -} - -.journeys { +.journeyView, +.journeysView, +.departuresView { min-height: 100vh; +} - .loadMore.flipped { +.journeysView { + .arrowButton.flipped { margin-top: 45px; } - - .icon-arrow1 { - height: 30px; - padding: 0; - } } -.journey { +.journeyView { tbody:not(:last-child) { border-bottom: 1px solid rgba(0, 0, 0, .2); } @@ -498,120 +457,86 @@ header { max-inline-size: 22px; margin: 0 .3em; } -} -.journey, -.journeys, -.departures { - display: flex; - flex-direction: column; - min-height: 100vh; - - tbody td:nth-child(2) span { - justify-content: start; + .remarks { + padding: 0; + width: 100%; + margin: 0; + + td { + margin: 0 10px; + text-align: left; + display: block; + } + + span { + vertical-align: middle; + } } } -.journeys tbody tr, -.departures tbody tr { - cursor: pointer; -} +.departuresView { + tbody td:nth-child(2) { + text-align: unset; + } -.journeys table a, -.journey table span, -.departures table span { - padding: 5px 3px; - display: flex; - justify-content: center; - align-items: center; - width: 100%; - text-decoration: none; - color: black; + tbody td { + padding: 5px 3px; + } } -.journey table a, -.departures table a { - padding: 5px 3px; - display: flex; - justify-content: center; - align-items: center; - text-decoration: none; - color: black; -} .modal { - display: flex; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; z-index: 1050; - overflow: hidden; + margin: auto; + background-color: white; + width: max-content; + padding: 15px; -webkit-overflow-scrolling: touch; - outline: 0; +} - .box { - margin: auto; - background-color: white; - width: max-content; - padding: 15px; - border-radius: 4px; - } +.modal.alert button { + float: right; +} - .alert button { - float: right; +.modal.select { + a { + width: 100%; + margin: 5px 0; + text-align: center; } - .select { - display: flex; - flex-direction: column; + a:first-child { + margin-top: unset; + } - a { - width: 100%; - margin: 5px 0; - text-align: center; - } + a:last-child { + margin-bottom: unset; + } +} - a:first-child { - margin-top: unset; - } +.modal.dialog { + padding: unset; - a:last-child { - margin-bottom: unset; - } - } + .header { + justify-content: space-between; + background-color: #5a5a5a; + color: white; + padding: 15px; - .dialog { - padding: unset; - border: 1px solid rgba(0, 0, 0, .4); + h4 { + margin: 0; + } - .header { - display: flex; - flex-direction: row; - justify-content: space-between; - background-color: #5a5a5a; - color: white; - padding: 15px; - border-top-right-radius: 3px; - border-top-left-radius: 3px; - - h4 { - margin: 0; - } - - .close { - margin: -15px; - padding: 10px; - border-left: 1px solid rgba(0, 0, 0, .4); - cursor: pointer; - content: url("data:image/svg+xml,%3Csvg width='30' height='30' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M5.293 5.293a1 1 0 0 1 1.414 0L12 10.586l5.293-5.293a1 1 0 1 1 1.414 1.414L13.414 12l5.293 5.293a1 1 0 0 1-1.414 1.414L12 13.414l-5.293 5.293a1 1 0 0 1-1.414-1.414L10.586 12 5.293 6.707a1 1 0 0 1 0-1.414' fill='%23fff'/%3E%3C/svg%3E"); - } + .icon-close { + margin: -15px; + padding: 10px; + border-left: 1px solid rgba(0, 0, 0, .4); + cursor: pointer; + } - .close:hover { - border-top-right-radius: 3px; - background: rgba(0, 0, 0, .4); - } + .icon-close:hover { + background: rgba(0, 0, 0, .4); } } } @@ -653,7 +578,6 @@ button, color: black; cursor: pointer; user-select: none; - display: inline-block; } button, .button { @@ -676,12 +600,14 @@ button.color:hover, .button.color:hover { background-color: rgba(70, 100, 255, .8); } -button:not(:first-child) { - margin-left: .2em; -} - -button:not(:last-child) { - margin-right: .2em; +.arrowButton { + cursor: pointer; + user-select: none; + height: 72px; + width: 72px; + margin: 0 auto; + transition: transform 150ms; + filter: invert(); } .selector { @@ -765,12 +691,12 @@ button:not(:last-child) { .button.go { flex-basis: 100%; - margin-right: auto; + justify-content: center; } } @media (max-width: 799px) { - .header { + header { .content { flex-grow: 1; } @@ -780,7 +706,7 @@ button:not(:last-child) { } } - #searchView { + .searchView { padding: 10px; } @@ -792,14 +718,15 @@ button:not(:last-child) { flex-wrap: unset; } - #journeysView { - .loadMore.flipped { - margin-top: 15px; + .journeysView { + .arrowButton { + margin: 15px auto; } } - .loadMore { + .arrowButton { width: 48px; + height: 48px; } } @@ -809,7 +736,7 @@ button:not(:last-child) { justify-content: center; } - #searchView { + .searchView { display: flex; justify-content: center; align-items: center; @@ -838,24 +765,11 @@ button:not(:last-child) { width: 80vw; } - td p { - display: inline; - margin-right: 5px; - } - - th { - padding: 10px 5px; - } - - .journeys table { + .journeysView table { margin: 15px auto; - - a { - padding: 10px 5px; - } } - .modal .dialog { + .modal.dialog { width: 400px; } } @@ -868,6 +782,10 @@ button:not(:last-child) { content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path style="fill: white;" d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/><path d="M0 0h24v24H0z" fill="none"/></svg>'); } +.icon-close { + content: url("data:image/svg+xml,%3Csvg width='30' height='30' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M5.293 5.293a1 1 0 0 1 1.414 0L12 10.586l5.293-5.293a1 1 0 1 1 1.414 1.414L13.414 12l5.293 5.293a1 1 0 0 1-1.414 1.414L12 13.414l-5.293 5.293a1 1 0 0 1-1.414-1.414L10.586 12 5.293 6.707a1 1 0 0 1 0-1.414' fill='%23fff'/%3E%3C/svg%3E"); +} + .icon-hint { content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>'); }