element
+ return false;
+ }
+ el = el.parentNode;
+ }
+ return false;
+ }
+
+ function getResultElement (el) {
+ while (el !== undefined) {
+ if (el.classList.contains('result')) {
+ return el;
+ }
+ el = el.parentNode;
+ }
+ return undefined;
+ }
+
+ function isImageResult (resultElement) {
+ return resultElement && resultElement.classList.contains('result-images');
+ }
+
+ searxng.on('.result', 'click', function (e) {
+ if (!isElementInDetail(e.target)) {
+ highlightResult(this)(true, true);
+ let resultElement = getResultElement(e.target);
+ if (isImageResult(resultElement)) {
+ e.preventDefault();
+ searxng.selectImage(resultElement);
+ }
+ }
+ });
+
+ searxng.on('.result a', 'focus', function (e) {
+ if (!isElementInDetail(e.target)) {
+ let resultElement = getResultElement(e.target);
+ if (resultElement && resultElement.getAttribute("data-vim-selected") === null) {
+ highlightResult(resultElement)(true);
+ }
+ if (isImageResult(resultElement)) {
+ searxng.selectImage(resultElement);
+ }
+ }
+ }, true);
+
+ /* common base for layouts */
+ var baseKeyBinding = {
+ 'Escape': {
+ key: 'ESC',
+ fun: removeFocus,
+ des: 'remove focus from the focused input',
+ cat: 'Control'
+ },
+ 'c': {
+ key: 'c',
+ fun: copyURLToClipboard,
+ des: 'copy url of the selected result to the clipboard',
+ cat: 'Results'
+ },
+ 'h': {
+ key: 'h',
+ fun: toggleHelp,
+ des: 'toggle help window',
+ cat: 'Other'
+ },
+ 'i': {
+ key: 'i',
+ fun: searchInputFocus,
+ des: 'focus on the search input',
+ cat: 'Control'
+ },
+ 'n': {
+ key: 'n',
+ fun: GoToNextPage(),
+ des: 'go to next page',
+ cat: 'Results'
+ },
+ 'o': {
+ key: 'o',
+ fun: openResult(false),
+ des: 'open search result',
+ cat: 'Results'
+ },
+ 'p': {
+ key: 'p',
+ fun: GoToPreviousPage(),
+ des: 'go to previous page',
+ cat: 'Results'
+ },
+ 'r': {
+ key: 'r',
+ fun: reloadPage,
+ des: 'reload page from the server',
+ cat: 'Control'
+ },
+ 't': {
+ key: 't',
+ fun: openResult(true),
+ des: 'open the result in a new tab',
+ cat: 'Results'
+ },
+ };
+ var keyBindingLayouts = {
+
+ "default": Object.assign(
+ { /* SearXNG layout */
+ 'ArrowLeft': {
+ key: '←',
+ fun: highlightResult('up'),
+ des: 'select previous search result',
+ cat: 'Results'
+ },
+ 'ArrowRight': {
+ key: '→',
+ fun: highlightResult('down'),
+ des: 'select next search result',
+ cat: 'Results'
+ },
+ }, baseKeyBinding),
+
+ 'vim': Object.assign(
+ { /* Vim-like Key Layout. */
+ 'b': {
+ key: 'b',
+ fun: scrollPage(-window.innerHeight),
+ des: 'scroll one page up',
+ cat: 'Navigation'
+ },
+ 'f': {
+ key: 'f',
+ fun: scrollPage(window.innerHeight),
+ des: 'scroll one page down',
+ cat: 'Navigation'
+ },
+ 'u': {
+ key: 'u',
+ fun: scrollPage(-window.innerHeight / 2),
+ des: 'scroll half a page up',
+ cat: 'Navigation'
+ },
+ 'd': {
+ key: 'd',
+ fun: scrollPage(window.innerHeight / 2),
+ des: 'scroll half a page down',
+ cat: 'Navigation'
+ },
+ 'g': {
+ key: 'g',
+ fun: scrollPageTo(-document.body.scrollHeight, 'top'),
+ des: 'scroll to the top of the page',
+ cat: 'Navigation'
+ },
+ 'v': {
+ key: 'v',
+ fun: scrollPageTo(document.body.scrollHeight, 'bottom'),
+ des: 'scroll to the bottom of the page',
+ cat: 'Navigation'
+ },
+ 'k': {
+ key: 'k',
+ fun: highlightResult('up'),
+ des: 'select previous search result',
+ cat: 'Results'
+ },
+ 'j': {
+ key: 'j',
+ fun: highlightResult('down'),
+ des: 'select next search result',
+ cat: 'Results'
+ },
+ 'y': {
+ key: 'y',
+ fun: copyURLToClipboard,
+ des: 'copy url of the selected result to the clipboard',
+ cat: 'Results'
+ },
+ }, baseKeyBinding)
+ }
+
+ var keyBindings = keyBindingLayouts[searxng.settings.hotkeys] || keyBindingLayouts.default;
+
+ searxng.on(document, "keydown", function (e) {
+ // check for modifiers so we don't break browser's hotkeys
+ if (
+ Object.prototype.hasOwnProperty.call(keyBindings, e.key)
+ && !e.ctrlKey && !e.altKey
+ && !e.shiftKey && !e.metaKey
+ ) {
+ var tagName = e.target.tagName.toLowerCase();
+ if (e.key === 'Escape') {
+ keyBindings[e.key].fun(e);
+ } else {
+ if (e.target === document.body || tagName === 'a' || tagName === 'button') {
+ e.preventDefault();
+ keyBindings[e.key].fun();
+ }
+ }
+ }
+ });
+
+ function highlightResult (which) {
+ return function (noScroll, keepFocus) {
+ var current = document.querySelector('.result[data-vim-selected]'),
+ effectiveWhich = which;
+ if (current === null) {
+ // no selection : choose the first one
+ current = document.querySelector('.result');
+ if (current === null) {
+ // no first one : there are no results
+ return;
+ }
+ // replace up/down actions by selecting first one
+ if (which === "down" || which === "up") {
+ effectiveWhich = current;
+ }
+ }
+
+ var next, results = document.querySelectorAll('.result');
+ results = Array.from(results); // convert NodeList to Array for further use
+
+ if (typeof effectiveWhich !== 'string') {
+ next = effectiveWhich;
+ } else {
+ switch (effectiveWhich) {
+ case 'visible':
+ var top = document.documentElement.scrollTop || document.body.scrollTop;
+ var bot = top + document.documentElement.clientHeight;
+
+ for (var i = 0; i < results.length; i++) {
+ next = results[i];
+ var etop = next.offsetTop;
+ var ebot = etop + next.clientHeight;
+
+ if ((ebot <= bot) && (etop > top)) {
+ break;
+ }
+ }
+ break;
+ case 'down':
+ next = results[results.indexOf(current) + 1] || current;
+ break;
+ case 'up':
+ next = results[results.indexOf(current) - 1] || current;
+ break;
+ case 'bottom':
+ next = results[results.length - 1];
+ break;
+ case 'top':
+ /* falls through */
+ default:
+ next = results[0];
+ }
+ }
+
+ if (next) {
+ current.removeAttribute('data-vim-selected');
+ next.setAttribute('data-vim-selected', 'true');
+ if (!keepFocus) {
+ var link = next.querySelector('h3 a') || next.querySelector('a');
+ if (link !== null) {
+ link.focus();
+ }
+ }
+ if (!noScroll) {
+ scrollPageToSelected();
+ }
+ }
+ };
+ }
+
+ function reloadPage () {
+ document.location.reload(true);
+ }
+
+ function removeFocus (e) {
+ const tagName = e.target.tagName.toLowerCase();
+ if (document.activeElement && (tagName === 'input' || tagName === 'select' || tagName === 'textarea')) {
+ document.activeElement.blur();
+ } else {
+ searxng.closeDetail();
+ }
+ }
+
+ function pageButtonClick (css_selector) {
+ return function () {
+ var button = document.querySelector(css_selector);
+ if (button) {
+ button.click();
+ }
+ };
+ }
+
+ function GoToNextPage () {
+ return pageButtonClick('nav#pagination .next_page button[type="submit"]');
+ }
+
+ function GoToPreviousPage () {
+ return pageButtonClick('nav#pagination .previous_page button[type="submit"]');
+ }
+
+ function scrollPageToSelected () {
+ var sel = document.querySelector('.result[data-vim-selected]');
+ if (sel === null) {
+ return;
+ }
+ var wtop = document.documentElement.scrollTop || document.body.scrollTop,
+ wheight = document.documentElement.clientHeight,
+ etop = sel.offsetTop,
+ ebot = etop + sel.clientHeight,
+ offset = 120;
+ // first element ?
+ if ((sel.previousElementSibling === null) && (ebot < wheight)) {
+ // set to the top of page if the first element
+ // is fully included in the viewport
+ window.scroll(window.scrollX, 0);
+ return;
+ }
+ if (wtop > (etop - offset)) {
+ window.scroll(window.scrollX, etop - offset);
+ } else {
+ var wbot = wtop + wheight;
+ if (wbot < (ebot + offset)) {
+ window.scroll(window.scrollX, ebot - wheight + offset);
+ }
+ }
+ }
+
+ function scrollPage (amount) {
+ return function () {
+ window.scrollBy(0, amount);
+ highlightResult('visible')();
+ };
+ }
+
+ function scrollPageTo (position, nav) {
+ return function () {
+ window.scrollTo(0, position);
+ highlightResult(nav)();
+ };
+ }
+
+ function searchInputFocus () {
+ window.scrollTo(0, 0);
+ var q = document.querySelector('#q');
+ q.focus();
+ if (q.setSelectionRange) {
+ var len = q.value.length;
+ q.setSelectionRange(len, len);
+ }
+ }
+
+ function openResult (newTab) {
+ return function () {
+ var link = document.querySelector('.result[data-vim-selected] h3 a');
+ if (link === null) {
+ link = document.querySelector('.result[data-vim-selected] > a');
+ }
+ if (link !== null) {
+ var url = link.getAttribute('href');
+ if (newTab) {
+ window.open(url);
+ } else {
+ window.location.href = url;
+ }
+ }
+ };
+ }
+
+ function initHelpContent (divElement) {
+ var categories = {};
+
+ for (var k in keyBindings) {
+ var key = keyBindings[k];
+ categories[key.cat] = categories[key.cat] || [];
+ categories[key.cat].push(key);
+ }
+
+ var sorted = Object.keys(categories).sort(function (a, b) {
+ return categories[b].length - categories[a].length;
+ });
+
+ if (sorted.length === 0) {
+ return;
+ }
+
+ var html = '
× ';
+ html += '
How to navigate SearXNG with hotkeys ';
+ html += '
';
+
+ for (var i = 0; i < sorted.length; i++) {
+ var cat = categories[sorted[i]];
+
+ var lastCategory = i === (sorted.length - 1);
+ var first = i % 2 === 0;
+
+ if (first) {
+ html += '';
+ }
+ html += '';
+
+ html += '' + cat[0].cat + ' ';
+ html += '';
+
+ for (var cj in cat) {
+ html += '' + cat[cj].key + ' ' + cat[cj].des + ' ';
+ }
+
+ html += ' ';
+ html += ' '; // col-sm-*
+
+ if (!first || lastCategory) {
+ html += ' '; // row
+ }
+ }
+
+ html += '
';
+
+ divElement.innerHTML = html;
+ }
+
+ function toggleHelp () {
+ var helpPanel = document.querySelector('#vim-hotkeys-help');
+ if (helpPanel === undefined || helpPanel === null) {
+ // first call
+ helpPanel = document.createElement('div');
+ helpPanel.id = 'vim-hotkeys-help';
+ helpPanel.className = 'dialog-modal';
+ initHelpContent(helpPanel);
+ var body = document.getElementsByTagName('body')[0];
+ body.appendChild(helpPanel);
+ } else {
+ // togggle hidden
+ helpPanel.classList.toggle('invisible');
+ return;
+ }
+ }
+
+ function copyURLToClipboard () {
+ var currentUrlElement = document.querySelector('.result[data-vim-selected] h3 a');
+ if (currentUrlElement === null) return;
+
+ const url = currentUrlElement.getAttribute('href');
+ navigator.clipboard.writeText(url);
+ }
+
+ searxng.scrollPageToSelected = scrollPageToSelected;
+ searxng.selectNext = highlightResult('down');
+ searxng.selectPrevious = highlightResult('up');
+});
diff --git a/searx/static/themes/marlo/src/js/main/mapresult.js b/searx/static/themes/marlo/src/js/main/mapresult.js
new file mode 100644
index 000000000..419bfa9fa
--- /dev/null
+++ b/searx/static/themes/marlo/src/js/main/mapresult.js
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: AGPL-3.0-or-later */
+/* global L */
+(function (w, d, searxng) {
+ 'use strict';
+
+ searxng.ready(function () {
+ searxng.on('.searxng_init_map', 'click', function (event) {
+ // no more request
+ this.classList.remove("searxng_init_map");
+
+ //
+ var leaflet_target = this.dataset.leafletTarget;
+ var map_lon = parseFloat(this.dataset.mapLon);
+ var map_lat = parseFloat(this.dataset.mapLat);
+ var map_zoom = parseFloat(this.dataset.mapZoom);
+ var map_boundingbox = JSON.parse(this.dataset.mapBoundingbox);
+ var map_geojson = JSON.parse(this.dataset.mapGeojson);
+
+ searxng.loadStyle('css/leaflet.css');
+ searxng.loadScript('js/leaflet.js', function () {
+ var map_bounds = null;
+ if (map_boundingbox) {
+ var southWest = L.latLng(map_boundingbox[0], map_boundingbox[2]);
+ var northEast = L.latLng(map_boundingbox[1], map_boundingbox[3]);
+ map_bounds = L.latLngBounds(southWest, northEast);
+ }
+
+ // init map
+ var map = L.map(leaflet_target);
+ // create the tile layer with correct attribution
+ var osmMapnikUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
+ var osmMapnikAttrib = 'Map data ©
OpenStreetMap contributors';
+ var osmMapnik = new L.TileLayer(osmMapnikUrl, {minZoom: 1, maxZoom: 19, attribution: osmMapnikAttrib});
+ var osmWikimediaUrl = 'https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png';
+ var osmWikimediaAttrib = 'Wikimedia maps | Maps data ©
OpenStreetMap contributors ';
+ var osmWikimedia = new L.TileLayer(osmWikimediaUrl, {minZoom: 1, maxZoom: 19, attribution: osmWikimediaAttrib});
+ // init map view
+ if (map_bounds) {
+ // TODO hack: https://github.com/Leaflet/Leaflet/issues/2021
+ // Still useful ?
+ setTimeout(function () {
+ map.fitBounds(map_bounds, {
+ maxZoom: 17
+ });
+ }, 0);
+ } else if (map_lon && map_lat) {
+ if (map_zoom) {
+ map.setView(new L.latLng(map_lat, map_lon), map_zoom);
+ } else {
+ map.setView(new L.latLng(map_lat, map_lon), 8);
+ }
+ }
+
+ map.addLayer(osmMapnik);
+
+ var baseLayers = {
+ "OSM Mapnik": osmMapnik,
+ "OSM Wikimedia": osmWikimedia,
+ };
+
+ L.control.layers(baseLayers).addTo(map);
+
+ if (map_geojson) {
+ L.geoJson(map_geojson).addTo(map);
+ } /* else if(map_bounds) {
+ L.rectangle(map_bounds, {color: "#ff7800", weight: 3, fill:false}).addTo(map);
+ } */
+ });
+
+ // this event occour only once per element
+ event.preventDefault();
+ });
+ });
+})(window, document, window.searxng);
diff --git a/searx/static/themes/marlo/src/js/main/preferences.js b/searx/static/themes/marlo/src/js/main/preferences.js
new file mode 100644
index 000000000..a0b853d61
--- /dev/null
+++ b/searx/static/themes/marlo/src/js/main/preferences.js
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: AGPL-3.0-or-later */
+(function (w, d, searxng) {
+ 'use strict';
+
+ if (searxng.endpoint !== 'preferences') {
+ return;
+ }
+
+ searxng.ready(function () {
+ let engine_descriptions = null;
+ function load_engine_descriptions () {
+ if (engine_descriptions == null) {
+ searxng.http("GET", "engine_descriptions.json").then(function (content) {
+ engine_descriptions = JSON.parse(content);
+ for (const [engine_name, description] of Object.entries(engine_descriptions)) {
+ let elements = d.querySelectorAll('[data-engine-name="' + engine_name + '"] .engine-description');
+ for (const element of elements) {
+ let source = ' (
' + searxng.settings.translations.Source + ': ' + description[1] + ' )';
+ element.innerHTML = description[0] + source;
+ }
+ }
+ });
+ }
+ }
+
+ for (const el of d.querySelectorAll('[data-engine-name]')) {
+ searxng.on(el, 'mouseenter', load_engine_descriptions);
+ }
+
+ const enableAllEngines = d.querySelectorAll(".enable-all-engines");
+ const disableAllEngines = d.querySelectorAll(".disable-all-engines");
+ const engineToggles = d.querySelectorAll('tbody input[type=checkbox][class~=checkbox-onoff]');
+ const toggleEngines = (enable) => {
+ for (const el of engineToggles) {
+ // check if element visible, so that only engines of the current category are modified
+ if (el.offsetParent !== null) el.checked = !enable;
+ }
+ };
+ for (const el of enableAllEngines) {
+ searxng.on(el, 'click', () => toggleEngines(true));
+ }
+ for (const el of disableAllEngines) {
+ searxng.on(el, 'click', () => toggleEngines(false));
+ }
+
+ const copyHashButton = d.querySelector("#copy-hash");
+ searxng.on(copyHashButton, 'click', (e) => {
+ e.preventDefault();
+ navigator.clipboard.writeText(copyHashButton.dataset.hash);
+ copyHashButton.innerText = copyHashButton.dataset.copiedText;
+ });
+ });
+})(window, document, window.searxng);
diff --git a/searx/static/themes/marlo/src/js/main/results.js b/searx/static/themes/marlo/src/js/main/results.js
new file mode 100644
index 000000000..7342f94b2
--- /dev/null
+++ b/searx/static/themes/marlo/src/js/main/results.js
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: AGPL-3.0-or-later */
+(function (w, d, searxng) {
+ 'use strict';
+
+ if (searxng.endpoint !== 'results') {
+ return;
+ }
+
+ searxng.ready(function () {
+ d.querySelectorAll('#urls img.image').forEach(
+ img =>
+ img.addEventListener(
+ 'error', () => {
+ img.style.display = 'none';
+ img.error = null;
+ }
+ ));
+
+ if (d.querySelector('#search_url button#copy_url')) {
+ d.querySelector('#search_url button#copy_url').style.display = "block";
+ }
+
+ searxng.on('.btn-collapse', 'click', function () {
+ var btnLabelCollapsed = this.getAttribute('data-btn-text-collapsed');
+ var btnLabelNotCollapsed = this.getAttribute('data-btn-text-not-collapsed');
+ var target = this.getAttribute('data-target');
+ var targetElement = d.querySelector(target);
+ var html = this.innerHTML;
+ if (this.classList.contains('collapsed')) {
+ html = html.replace(btnLabelCollapsed, btnLabelNotCollapsed);
+ } else {
+ html = html.replace(btnLabelNotCollapsed, btnLabelCollapsed);
+ }
+ this.innerHTML = html;
+ this.classList.toggle('collapsed');
+ targetElement.classList.toggle('invisible');
+ });
+
+ searxng.on('.media-loader', 'click', function () {
+ var target = this.getAttribute('data-target');
+ var iframe_load = d.querySelector(target + ' > iframe');
+ var srctest = iframe_load.getAttribute('src');
+ if (srctest === null || srctest === undefined || srctest === false) {
+ iframe_load.setAttribute('src', iframe_load.getAttribute('data-src'));
+ }
+ });
+
+ searxng.on('#copy_url', 'click', function () {
+ var target = this.parentElement.querySelector('pre');
+ navigator.clipboard.writeText(target.innerText);
+ this.innerText = this.dataset.copiedText;
+ });
+
+ searxng.selectImage = function (resultElement) {
+ /* eslint no-unused-vars: 0 */
+ if (resultElement) {
+ // load full size image in background
+ const imgElement = resultElement.querySelector('.result-images-source img');
+ const thumbnailElement = resultElement.querySelector('.image_thumbnail');
+ const detailElement = resultElement.querySelector('.detail');
+ if (imgElement) {
+ const imgSrc = imgElement.getAttribute('data-src');
+ if (imgSrc) {
+ const loader = d.createElement('div');
+ const imgLoader = new Image();
+
+ loader.classList.add('loader');
+ detailElement.appendChild(loader);
+
+ imgLoader.onload = e => {
+ imgElement.src = imgSrc;
+ loader.remove();
+ };
+ imgLoader.onerror = e => {
+ loader.remove();
+ };
+ imgLoader.src = imgSrc;
+ imgElement.src = thumbnailElement.src;
+ imgElement.removeAttribute('data-src');
+ }
+ }
+ }
+ d.getElementById('results').classList.add('image-detail-open');
+ searxng.scrollPageToSelected();
+ }
+
+ searxng.closeDetail = function (e) {
+ d.getElementById('results').classList.remove('image-detail-open');
+ searxng.scrollPageToSelected();
+ }
+ searxng.on('.result-detail-close', 'click', e => {
+ e.preventDefault();
+ searxng.closeDetail();
+ });
+ searxng.on('.result-detail-previous', 'click', e => {
+ e.preventDefault();
+ searxng.selectPrevious(false)
+ });
+ searxng.on('.result-detail-next', 'click', e => {
+ e.preventDefault();
+ searxng.selectNext(false);
+ });
+
+ w.addEventListener('scroll', function () {
+ var e = d.getElementById('backToTop'),
+ scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
+ results = d.getElementById('results');
+ if (e !== null) {
+ if (scrollTop >= 100) {
+ results.classList.add('scrolling');
+ } else {
+ results.classList.remove('scrolling');
+ }
+ }
+ }, true);
+
+ });
+
+})(window, document, window.searxng);
diff --git a/searx/static/themes/marlo/src/js/main/search.js b/searx/static/themes/marlo/src/js/main/search.js
new file mode 100644
index 000000000..ac1ece535
--- /dev/null
+++ b/searx/static/themes/marlo/src/js/main/search.js
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: AGPL-3.0-or-later */
+/* global AutoComplete */
+(function (w, d, searxng) {
+ 'use strict';
+
+ var qinput_id = "q", qinput;
+
+ const isMobile = window.matchMedia("only screen and (max-width: 50em)").matches;
+
+ function submitIfQuery () {
+ if (qinput.value.length > 0) {
+ var search = document.getElementById('search');
+ setTimeout(search.submit.bind(search), 0);
+ }
+ }
+
+ function createClearButton (qinput) {
+ var cs = document.getElementById('clear_search');
+ var updateClearButton = function () {
+ if (qinput.value.length === 0) {
+ cs.classList.add("empty");
+ } else {
+ cs.classList.remove("empty");
+ }
+ };
+
+ // update status, event listener
+ updateClearButton();
+ cs.addEventListener('click', function (ev) {
+ qinput.value = '';
+ qinput.focus();
+ updateClearButton();
+ ev.preventDefault();
+ });
+ qinput.addEventListener('keyup', updateClearButton, false);
+ }
+
+ searxng.ready(function () {
+ qinput = d.getElementById(qinput_id);
+
+ if (qinput !== null) {
+ // clear button
+ createClearButton(qinput);
+
+ // autocompleter
+ if (searxng.settings.autocomplete_provider) {
+ searxng.autocomplete = AutoComplete.call(w, {
+ Url: "./autocompleter",
+ EmptyMessage: searxng.settings.translations.no_item_found,
+ HttpMethod: searxng.settings.http_method,
+ HttpHeaders: {
+ "Content-type": "application/x-www-form-urlencoded",
+ "X-Requested-With": "XMLHttpRequest"
+ },
+ MinChars: searxng.settings.autocomplete_min,
+ Delay: 300,
+ _Position: function () {},
+ _Open: function () {
+ var params = this;
+ Array.prototype.forEach.call(this.DOMResults.getElementsByTagName("li"), function (li) {
+ if (li.getAttribute("class") != "locked") {
+ li.onmousedown = function () {
+ params._Select(li);
+ };
+ }
+ });
+ },
+ _Select: function (item) {
+ AutoComplete.defaults._Select.call(this, item);
+ var form = item.closest('form');
+ if (form) {
+ form.submit();
+ }
+ },
+ _MinChars: function () {
+ if (this.Input.value.indexOf('!') > -1) {
+ return 0;
+ } else {
+ return AutoComplete.defaults._MinChars.call(this);
+ }
+ },
+ KeyboardMappings: Object.assign({}, AutoComplete.defaults.KeyboardMappings, {
+ "KeyUpAndDown_up": Object.assign({}, AutoComplete.defaults.KeyboardMappings.KeyUpAndDown_up, {
+ Callback: function (event) {
+ AutoComplete.defaults.KeyboardMappings.KeyUpAndDown_up.Callback.call(this, event);
+ var liActive = this.DOMResults.querySelector("li.active");
+ if (liActive) {
+ AutoComplete.defaults._Select.call(this, liActive);
+ }
+ },
+ }),
+ "Tab": Object.assign({}, AutoComplete.defaults.KeyboardMappings.Enter, {
+ Conditions: [{
+ Is: 9,
+ Not: false
+ }],
+ Callback: function (event) {
+ if (this.DOMResults.getAttribute("class").indexOf("open") != -1) {
+ var liActive = this.DOMResults.querySelector("li.active");
+ if (liActive !== null) {
+ AutoComplete.defaults._Select.call(this, liActive);
+ event.preventDefault();
+ }
+ }
+ },
+ })
+ }),
+ }, "#" + qinput_id);
+ }
+
+ /*
+ Monkey patch autocomplete.js to fix a bug
+ With the POST method, the values are not URL encoded: query like "1 + 1" are sent as "1 1" since space are URL encoded as plus.
+ See HTML specifications:
+ * HTML5: https://url.spec.whatwg.org/#concept-urlencoded-serializer
+ * HTML4: https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
+
+ autocomplete.js does not URL encode the name and values:
+ https://github.com/autocompletejs/autocomplete.js/blob/87069524f3b95e68f1b54d8976868e0eac1b2c83/src/autocomplete.ts#L665
+
+ The monkey patch overrides the compiled version of the ajax function.
+ See https://github.com/autocompletejs/autocomplete.js/blob/87069524f3b95e68f1b54d8976868e0eac1b2c83/dist/autocomplete.js#L143-L158
+ The patch changes only the line 156 from
+ params.Request.send(params._QueryArg() + "=" + params._Pre());
+ to
+ params.Request.send(encodeURIComponent(params._QueryArg()) + "=" + encodeURIComponent(params._Pre()));
+
+ Related to:
+ * https://github.com/autocompletejs/autocomplete.js/issues/78
+ * https://github.com/searxng/searxng/issues/1695
+ */
+ AutoComplete.prototype.ajax = function (params, request, timeout) {
+ if (timeout === void 0) { timeout = true; }
+ if (params.$AjaxTimer) {
+ window.clearTimeout(params.$AjaxTimer);
+ }
+ if (timeout === true) {
+ params.$AjaxTimer = window.setTimeout(AutoComplete.prototype.ajax.bind(null, params, request, false), params.Delay);
+ } else {
+ if (params.Request) {
+ params.Request.abort();
+ }
+ params.Request = request;
+ params.Request.send(encodeURIComponent(params._QueryArg()) + "=" + encodeURIComponent(params._Pre()));
+ }
+ };
+
+ if (!isMobile && document.querySelector('.index_endpoint')) {
+ qinput.focus();
+ }
+ }
+
+ // Additionally to searching when selecting a new category, we also
+ // automatically start a new search request when the user changes a search
+ // filter (safesearch, time range or language) (this requires JavaScript
+ // though)
+ if (
+ qinput !== null
+ && searxng.settings.search_on_category_select
+ // If .search_filters is undefined (invisible) we are on the homepage and
+ // hence don't have to set any listeners
+ && d.querySelector(".search_filters") != null
+ ) {
+ searxng.on(d.getElementById('safesearch'), 'change', submitIfQuery);
+ searxng.on(d.getElementById('time_range'), 'change', submitIfQuery);
+ searxng.on(d.getElementById('language'), 'change', submitIfQuery);
+ }
+
+ // most common browsers at the time of writing this support :has, except for Firefox
+ // can be removed when Firefox / Firefox ESL starts supporting it as well
+ try {
+ // this fails when the browser does not support :has
+ d.querySelector("html:has(body)");
+ } catch (_) {
+ // manually deselect the old selection when a new category is selected
+ for (let button of d.querySelectorAll("button.category_button")) {
+ searxng.on(button, 'click', () => {
+ const selected = d.querySelector("button.category_button.selected");
+ console.log(selected);
+ selected.classList.remove("selected");
+ })
+ }
+ }
+ });
+
+})(window, document, window.searxng);
diff --git a/searx/static/themes/marlo/src/less/animations.less b/searx/static/themes/marlo/src/less/animations.less
new file mode 100644
index 000000000..75c98308f
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/animations.less
@@ -0,0 +1,19 @@
+.dialog-modal {
+ animation-name: dialogmodal;
+ animation-duration: 0.13s;
+
+ @keyframes dialogmodal {
+ 0% {
+ opacity: 0;
+ }
+
+ 50% {
+ opacity: 0.5;
+ transform: translate(-50%, -50%) scale(1.05);
+ }
+ }
+}
+
+input.checkbox-onoff[type="checkbox"]::before {
+ transition: left 0.25s;
+}
diff --git a/searx/static/themes/marlo/src/less/autocomplete.less b/searx/static/themes/marlo/src/less/autocomplete.less
new file mode 100644
index 000000000..bb2e1890f
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/autocomplete.less
@@ -0,0 +1,75 @@
+/*! Autocomplete.js v2.6.3 | license MIT | (c) 2017, Baptiste Donaux | http://autocomplete-js.com */
+
+.autocomplete {
+ position: absolute;
+ width: @search-width;
+ max-height: 0;
+ overflow-y: hidden;
+ .ltr-text-align-left();
+
+ .rounded-corners;
+
+ &:active,
+ &:focus,
+ &:hover {
+ background-color: var(--color-autocomplete-background);
+ }
+
+ &:empty {
+ display: none;
+ }
+
+ > ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+
+ > li {
+ cursor: pointer;
+ padding: 0.5rem 1rem;
+
+ &.active,
+ &:active,
+ &:focus,
+ &:hover {
+ background-color: var(--color-autocomplete-background-hover);
+
+ a:active,
+ a:focus,
+ a:hover {
+ text-decoration: none;
+ }
+ }
+
+ &.locked {
+ cursor: inherit;
+ }
+ }
+ }
+
+ &.open {
+ display: block;
+ background-color: var(--color-autocomplete-background);
+ color: var(--color-autocomplete-font);
+ max-height: 32rem;
+ overflow-y: auto;
+ z-index: 100;
+ margin-top: 3.5rem;
+ border-radius: 0.8rem;
+ box-shadow: 0 2px 8px rgb(34 38 46 / 25%);
+
+ &:empty {
+ display: none;
+ }
+ }
+}
+
+@media screen and (max-width: @phone) {
+ .autocomplete {
+ width: 100%;
+
+ > ul > li {
+ padding: 1rem;
+ }
+ }
+}
diff --git a/searx/static/themes/marlo/src/less/code.less b/searx/static/themes/marlo/src/less/code.less
new file mode 100644
index 000000000..d6553feb8
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/code.less
@@ -0,0 +1,51 @@
+@import "../generated/pygments.less";
+
+.codelines {
+ margin: @results-margin 0 0 0;
+ padding: @result-padding 0 0 0;
+}
+
+.code-highlight-sxng() {
+ .code-highlight {
+ pre {
+ overflow: auto;
+ margin: 0;
+ padding: 0 0 0.75rem 0;
+ }
+
+ .linenos {
+ user-select: none;
+ cursor: default;
+
+ &::selection {
+ background: transparent; /* WebKit/Blink Browsers */
+ }
+
+ &::-moz-selection {
+ background: transparent; /* Gecko Browsers */
+ }
+ margin-right: 8px;
+ text-align: right;
+ }
+
+ span.linenos {
+ color: #64708d;
+ }
+ }
+}
+
+.code-highlight-sxng();
+
+/// Dark Theme (autoswitch based on device pref)
+@media (prefers-color-scheme: dark) {
+ :root.theme-auto {
+ .code-highlight-dark();
+ .code-highlight-sxng();
+ }
+}
+
+// Dark Theme by preferences
+:root.theme-dark {
+ .code-highlight-dark();
+ .code-highlight-sxng();
+}
diff --git a/searx/static/themes/marlo/src/less/definitions.less b/searx/static/themes/marlo/src/less/definitions.less
new file mode 100644
index 000000000..45d5c878d
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/definitions.less
@@ -0,0 +1,277 @@
+/*
+ * SearXNG, A privacy-respecting, hackable metasearch engine
+ *
+ * To change the colors of the site, simple edit this variables
+ */
+
+/// Light Theme
+:root {
+ /// Base Colors
+ --color-base-font: #444;
+ --color-base-font-rgb: 68, 68, 68;
+ --color-base-background: #fff;
+ --color-base-background-mobile: #f2f5f8;
+ --color-url-font: #334999;
+ --color-url-visited-font: #9822c3;
+ /// Header Colors
+ --color-header-background: #fdfbff;
+ --color-header-border: #ddd;
+ /// Footer Colors
+ --color-footer-background: #fdfbff;
+ --color-footer-border: #ddd;
+ /// Sidebar Colors
+ --color-sidebar-border: #ddd;
+ --color-sidebar-font: #000;
+ --color-sidebar-background: #fff;
+ /// BackToTop Colors
+ --color-backtotop-font: #444;
+ --color-backtotop-border: #ddd;
+ --color-backtotop-background: #fff;
+ /// Button Colors
+ --color-btn-background: #3050ff;
+ --color-btn-font: #fff;
+ --color-show-btn-background: #bbb;
+ --color-show-btn-font: #000;
+ /// Search Input Colors
+ --color-search-border: #bbb;
+ --color-search-shadow: 0 2px 8px rgb(34 38 46 / 25%);
+ --color-search-background: #fff;
+ --color-search-font: #222;
+ --color-search-background-hover: #3050ff;
+ /// Modal Colors
+ --color-error: #db3434;
+ --color-error-background: lighten(#db3434, 40%);
+ --color-warning: #dbba34;
+ --color-warning-background: lighten(#dbba34, 40%);
+ --color-success: #42db34;
+ --color-success-background: lighten(#42db34, 40%);
+ /// Categories Colors
+ --color-categories-item-selected-font: #3050ff;
+ --color-categories-item-border-selected: #3050ff;
+ /// Autocomplete Colors
+ --color-autocomplete-font: #000;
+ --color-autocomplete-border: #bbb;
+ --color-autocomplete-shadow: 0 2px 8px rgb(34 38 46 / 25%);
+ --color-autocomplete-background: #fff;
+ --color-autocomplete-background-hover: #e3e3e3;
+ /// Answer Colors
+ --color-answer-font: #444; // same as --color-base-font
+ --color-answer-background: #fff;
+ /// Results Colors
+ --color-result-background: #fff;
+ --color-result-border: #ddd;
+ --color-result-url-font: #000;
+ --color-result-vim-selected: #f7f7f7;
+ --color-result-vim-arrow: #000bbb;
+ --color-result-description-highlight-font: #000;
+ --color-result-link-font: #000bbb;
+ --color-result-link-font-highlight: #000bbb;
+ --color-result-link-visited-font: #9822c3;
+ --color-result-publishdate-font: #777;
+ --color-result-engines-font: #545454;
+ --color-result-search-url-border: #ddd;
+ --color-result-search-url-font: #000;
+ // Images Colors
+ --color-result-image-span-font: #444;
+ --color-result-image-span-font-selected: #fff;
+ --color-result-image-background: #fff;
+ /// Settings Colors
+ --color-settings-tr-hover: #ebebeb;
+ --color-settings-engine-description-font: #545454;
+ --color-settings-table-group-background: #0001;
+ /// Detail modal
+ --color-result-detail-font: #fff;
+ --color-result-detail-label-font: lightgray;
+ --color-result-detail-background: #242424;
+ --color-result-detail-hr: #555;
+ --color-result-detail-link: #8af;
+ --color-result-detail-loader-border: rgba(255, 255, 255, 0.2);
+ --color-result-detail-loader-borderleft: rgba(0, 0, 0, 0);
+ /// Toolkit Colors
+ --color-toolkit-badge-font: #fff;
+ --color-toolkit-badge-background: #545454;
+ --color-toolkit-kbd-font: #fff;
+ --color-toolkit-kbd-background: #000;
+ --color-toolkit-dialog-border: #ddd;
+ --color-toolkit-dialog-background: #fff;
+ --color-toolkit-tabs-label-border: #fff;
+ --color-toolkit-tabs-section-border: #ddd;
+ --color-toolkit-select-background: #e1e1e1;
+ --color-toolkit-select-border: #ddd;
+ --color-toolkit-select-background-hover: #bbb;
+ --color-toolkit-input-text-font: #222;
+ --color-toolkit-checkbox-onoff-off-background: #ddd;
+ --color-toolkit-checkbox-onoff-on-background: #ddd;
+ --color-toolkit-checkbox-onoff-on-mark-background: #3050ff;
+ --color-toolkit-checkbox-onoff-on-mark-color: #fff;
+ --color-toolkit-checkbox-onoff-off-mark-background: #aaa;
+ --color-toolkit-checkbox-onoff-off-mark-color: #fff;
+ --color-toolkit-checkbox-label-background: #ddd;
+ --color-toolkit-checkbox-label-border: #ddd;
+ --color-toolkit-checkbox-input-border: #3050ff;
+ --color-toolkit-engine-tooltip-border: #ddd;
+ --color-toolkit-engine-tooltip-background: #fff;
+ --color-toolkit-loader-border: rgba(0, 0, 0, 0.2);
+ --color-toolkit-loader-borderleft: rgba(255, 255, 255, 0);
+ --color-doc-code: #003;
+ --color-doc-code-background: #ddeaff;
+}
+
+.dark-themes() {
+ /// Base Colors
+ --color-base-font: #bbb;
+ --color-base-font-rgb: 187, 187, 187;
+ --color-base-background: #222428;
+ --color-base-background-mobile: #222428;
+ --color-url-font: #8af;
+ --color-url-visited-font: #c09cd9;
+ /// Header Colors
+ --color-header-background: #1e1e22;
+ --color-header-border: #333;
+ /// Footer Colors
+ --color-footer-background: #1e1e22;
+ --color-footer-border: #333;
+ /// Sidebar Colors
+ --color-sidebar-border: #555;
+ --color-sidebar-font: #fff;
+ --color-sidebar-background: #292c34;
+ /// BackToTop Colors
+ --color-backtotop-font: #bbb;
+ --color-backtotop-border: #333;
+ --color-backtotop-background: #2b2e36;
+ /// Button Colors
+ --color-btn-background: #58f;
+ --color-btn-font: #222;
+ --color-show-btn-background: #555;
+ --color-show-btn-font: #fff;
+ /// Search Input Colors
+ --color-search-border: #555;
+ --color-search-shadow: 0 2px 8px rgb(34 38 46 / 25%);
+ --color-search-background: #2b2e36;
+ --color-search-font: #fff;
+ --color-search-background-hover: #58f;
+ /// Modal Colors
+ --color-error: #f55b5b;
+ --color-error-background: darken(#db3434, 40%);
+ --color-warning: #f1d561;
+ --color-warning-background: darken(#dbba34, 40%);
+ --color-success: #79f56e;
+ --color-success-background: darken(#42db34, 40%);
+ /// Categories Colors
+ --color-categories-item-selected-font: #58f;
+ --color-categories-item-border-selected: #58f;
+ /// Autocomplete Colors
+ --color-autocomplete-font: #fff;
+ --color-autocomplete-border: #555;
+ --color-autocomplete-shadow: 0 2px 8px rgb(34 38 46 / 25%);
+ --color-autocomplete-background: #2b2e36;
+ --color-autocomplete-background-hover: #1e1e22;
+ /// Answer Colors
+ --color-answer-font: #bbb; // same as --color-base-font
+ --color-answer-background: #26292f;
+ /// Results Colors
+ --color-result-background: #26292f;
+ --color-result-border: #333;
+ --color-result-url-font: #fff;
+ --color-result-vim-selected: #1f1f23cc;
+ --color-result-vim-arrow: #8af;
+ --color-result-description-highlight-font: #fff;
+ --color-result-link-font: #8af;
+ --color-result-link-font-highlight: #8af;
+ --color-result-link-visited-font: #c09cd9;
+ --color-result-publishdate-font: #888;
+ --color-result-engines-font: #a4a4a4;
+ --color-result-search-url-border: #555;
+ --color-result-search-url-font: #fff;
+ /// Detail modal : same as the light version
+ --color-result-detail-font: #fff;
+ --color-result-detail-label-font: lightgray;
+ --color-result-detail-background: #1a1a1c;
+ --color-result-detail-hr: #555;
+ --color-result-detail-link: #8af;
+ --color-result-detail-loader-border: rgba(255, 255, 255, 0.2);
+ --color-result-detail-loader-borderleft: rgba(0, 0, 0, 0);
+ // Images Colors
+ --color-result-image-span-font: #bbb;
+ --color-result-image-span-font-selected: #222;
+ --color-result-image-background: #222;
+ /// Settings Colors
+ --color-settings-tr-hover: #2c2c32;
+ --color-settings-engine-description-font: darken(#dcdcdc, 30%);
+ --color-settings-table-group-background: #1b1b21;
+ /// Toolkit Colors
+ --color-toolkit-badge-font: #fff;
+ --color-toolkit-badge-background: #555;
+ --color-toolkit-kbd-font: #000;
+ --color-toolkit-kbd-background: #fff;
+ --color-toolkit-dialog-border: #555;
+ --color-toolkit-dialog-background: #1e1e22;
+ --color-toolkit-tabs-label-border: #222;
+ --color-toolkit-tabs-section-border: #555;
+ --color-toolkit-select-background: #313338;
+ --color-toolkit-select-border: #555;
+ --color-toolkit-select-background-hover: #373b49;
+ --color-toolkit-input-text-font: #fff;
+ --color-toolkit-checkbox-onoff-off-background: #313338;
+ --color-toolkit-checkbox-onoff-on-background: #313338;
+ --color-toolkit-checkbox-onoff-on-mark-background: #58f;
+ --color-toolkit-checkbox-onoff-on-mark-color: #222;
+ --color-toolkit-checkbox-onoff-off-mark-background: #ddd;
+ --color-toolkit-checkbox-onoff-off-mark-color: #222;
+ --color-toolkit-checkbox-label-background: #222;
+ --color-toolkit-checkbox-label-border: #333;
+ --color-toolkit-checkbox-input-border: #58f;
+ --color-toolkit-engine-tooltip-border: #333;
+ --color-toolkit-engine-tooltip-background: #222;
+ --color-toolkit-loader-border: rgba(255, 255, 255, 0.2);
+ --color-toolkit-loader-borderleft: rgba(0, 0, 0, 0);
+ --color-doc-code: #ddd;
+ --color-doc-code-background: #4d5a6f;
+}
+
+/// Dark Theme (autoswitch based on device pref)
+@media (prefers-color-scheme: dark) {
+ :root.theme-auto {
+ .dark-themes();
+ }
+}
+
+// Dark Theme by preferences
+:root.theme-dark {
+ .dark-themes();
+}
+
+/// General Size
+@results-width: 45rem;
+@results-sidebar-width: 25rem;
+@results-offset: 10rem;
+@results-tablet-offset: 0.5rem;
+@results-gap: 5rem;
+@results-margin: 0.125rem;
+@result-padding: 1rem;
+@results-image-row-height: 12rem;
+@results-image-row-height-phone: 6rem;
+@search-width: 44rem;
+// heigh of #search, see detail.less
+@search-height: 7.6rem;
+
+/// Device Size
+/// @desktop > @tablet
+@tablet: 79.75em; // see https://github.com/searxng/searxng/issues/874
+@phone: 50em;
+@small-phone: 35em;
+@ultra-small-phone: 20rem;
+
+/// From style.less
+@stacked-bar-chart: rgb(0, 0, 0);
+
+/// Load fonts from this directory.
+@icon-font-path: "../../../fonts/";
+//** File name for all font files.
+@icon-font-name: "glyphicons-halflings-regular";
+//** Element ID within SVG icon file.
+@icon-font-svg-id: "glyphicons_halflingsregular";
+
+// decoration of the select HTML elements
+@select-light-svg-path: "../svg/select-light.svg";
+@select-dark-svg-path: "../svg/select-dark.svg";
diff --git a/searx/static/themes/marlo/src/less/detail.less b/searx/static/themes/marlo/src/less/detail.less
new file mode 100644
index 000000000..fd7858a1e
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/detail.less
@@ -0,0 +1,254 @@
+#main_results #results.image-detail-open.only_template_images {
+ width: min(98%, 59.25rem) !important;
+}
+
+#main_results #results.only_template_images.image-detail-open #backToTop {
+ .ltr-left(56.75rem) !important;
+ .ltr-right(inherit);
+}
+
+article.result-images .detail {
+ display: none;
+}
+
+#results.image-detail-open article.result-images[data-vim-selected] .detail {
+ display: flex;
+ flex-direction: column;
+ position: fixed;
+ .ltr-left(60rem);
+ .ltr-right(0);
+ top: @search-height;
+ transition: top 0.064s ease-in 0s;
+ bottom: 0;
+ background: var(--color-result-detail-background);
+ border: 1px solid var(--color-result-detail-background);
+ z-index: 10000;
+ padding: 4rem 3rem 3rem 3rem;
+
+ a.result-images-source {
+ display: block;
+ flex: 1;
+ text-align: left;
+ width: 100%;
+ border: none;
+ text-decoration: none;
+
+ img {
+ padding: 0;
+ margin: 0;
+ border: none;
+ object-fit: contain;
+ width: inherit;
+ height: inherit;
+ max-width: 100%;
+ min-height: inherit;
+ max-height: calc(100vh - 25rem - 7rem);
+ background: inherit;
+ }
+ }
+
+ .result-images-labels {
+ color: var(--color-result-detail-font);
+ height: 19rem;
+
+ hr {
+ border-top: 1px solid var(--color-result-detail-hr);
+ border-bottom: none;
+ }
+
+ h4 {
+ height: 2rem;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-size: 0.9rem;
+ margin-bottom: 0;
+ }
+
+ p {
+ color: var(--color-result-detail-label-font);
+ font-size: 0.9rem;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ margin: 0.8rem 0;
+
+ span {
+ display: inline-block;
+ width: 12rem;
+ }
+ }
+
+ h4,
+ p,
+ a {
+ .ltr-text-align-left();
+ }
+
+ p.result-content {
+ height: 2rem;
+ line-height: unset;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ p.result-url {
+ white-space: nowrap;
+ overflow-x: hidden;
+ overflow-y: hidden;
+ text-overflow: ellipsis;
+ }
+
+ p.result-content:hover,
+ p.result-url:hover {
+ position: relative;
+ overflow: inherit !important;
+ background: var(--color-result-detail-background);
+ text-overflow: inherit !important;
+ }
+
+ a,
+ a:visited,
+ a:hover,
+ a:active {
+ color: var(--color-result-detail-link);
+ }
+
+ a:hover {
+ text-decoration: underline;
+ }
+ }
+
+ a.result-detail-close {
+ top: 1rem;
+ .ltr-left(1rem);
+ padding: 0.4rem;
+ }
+
+ a.result-detail-previous {
+ top: 1rem;
+ .ltr-right(6rem);
+ // center the icon by moving it slightly on the left
+ padding-top: 0.4rem;
+ .ltr-padding-right(0.5rem);
+ padding-bottom: 0.4rem;
+ .ltr-padding-left(0.3rem);
+ }
+
+ a.result-detail-next {
+ top: 1rem;
+ .ltr-right(2rem);
+ padding: 0.4rem;
+ }
+
+ a.result-detail-close,
+ a.result-detail-next,
+ a.result-detail-previous {
+ border-radius: 50%;
+ display: block;
+ width: 1.5rem;
+ height: 1.5rem;
+ position: absolute;
+ filter: opacity(40%);
+ z-index: 2000002;
+
+ span {
+ display: block;
+ width: 1.5rem;
+ height: 1.5rem;
+ text-align: center;
+ }
+ }
+
+ a.result-detail-next,
+ a.result-detail-previous {
+ span::before {
+ // vertical center small icons
+ vertical-align: sub;
+ }
+ }
+
+ a.result-detail-close,
+ a.result-detail-close:visited,
+ a.result-detail-close:hover,
+ a.result-detail-close:active,
+ a.result-detail-previous,
+ a.result-detail-previous:visited,
+ a.result-detail-previous:hover,
+ a.result-detail-previous:active,
+ a.result-detail-next,
+ a.result-detail-next:visited,
+ a.result-detail-next:hover,
+ a.result-detail-next:active {
+ color: var(--color-result-detail-font);
+ background: var(--color-result-detail-background);
+ border: 1px solid var(--color-result-detail-font);
+ }
+
+ a.result-detail-close:focus,
+ a.result-detail-close:hover,
+ a.result-detail-previous:focus,
+ a.result-detail-previous:hover,
+ a.result-detail-next:focus,
+ a.result-detail-next:hover {
+ filter: opacity(80%);
+ }
+
+ .loader {
+ position: absolute;
+ top: 1rem;
+ .ltr-right(50%);
+ border-top: 0.5em solid var(--color-result-detail-loader-border);
+ border-right: 0.5em solid var(--color-result-detail-loader-border);
+ border-bottom: 0.5em solid var(--color-result-detail-loader-border);
+ border-left: 0.5em solid var(--color-result-detail-loader-borderleft);
+ }
+}
+
+#results.image-detail-open.scrolling article.result-images[data-vim-selected] .detail {
+ top: 0;
+
+ a.result-images-source img {
+ max-height: calc(100vh - 25rem);
+ }
+}
+
+@media screen and (max-width: @tablet) {
+ #results.image-detail-open article.result-images[data-vim-selected] .detail {
+ top: 0;
+ .ltr-left(0);
+
+ a.result-images-source {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+
+ img {
+ width: 100%;
+ max-height: calc(100vh - 24rem);
+ }
+ }
+
+ a.result-detail-next {
+ .ltr-right(1rem);
+ }
+ }
+}
+
+@media screen and (max-width: @phone) {
+ #results.image-detail-open article.result-images[data-vim-selected] .detail {
+ top: 0;
+ .ltr-left(0);
+ padding: 1rem;
+
+ a.result-images-source img {
+ width: 100%;
+ max-height: calc(100vh - 20rem);
+ margin: 0;
+ }
+
+ .result-images-labels p span {
+ width: inherit;
+ .ltr-margin-right(1rem);
+ }
+ }
+}
diff --git a/searx/static/themes/marlo/src/less/embedded.less b/searx/static/themes/marlo/src/less/embedded.less
new file mode 100644
index 000000000..2e9216ad2
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/embedded.less
@@ -0,0 +1,33 @@
+iframe[src^="https://w.soundcloud.com"] {
+ height: 120px;
+}
+
+iframe[src^="https://www.deezer.com"] {
+ // The real size is 92px, but 94px are needed to avoid an inner scrollbar of
+ // the embedded HTML.
+ height: 94px;
+}
+
+iframe[src^="https://www.mixcloud.com"] {
+ // the embedded player from mixcloud has some quirks: initial there is an
+ // issue with an image URL that is blocked since it is an a Cross-Origin
+ // request. The alternative text (
then cause an
+ // scrollbar in the inner of the iframe we can't avoid. Another quirk comes
+ // when pressing the play button, somtimes the shown player has an height of
+ // 200px, somtimes 250px.
+ height: 250px;
+}
+
+iframe[src^="https://bandcamp.com/EmbeddedPlayer"] {
+ // show playlist
+ height: 350px;
+}
+
+iframe[src^="https://bandcamp.com/EmbeddedPlayer/track"] {
+ // hide playlist
+ height: 120px;
+}
+
+iframe[src^="https://genius.com/songs"] {
+ height: 65px;
+}
diff --git a/searx/static/themes/marlo/src/less/index.less b/searx/static/themes/marlo/src/less/index.less
new file mode 100644
index 000000000..8590d0c3b
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/index.less
@@ -0,0 +1,51 @@
+#main_index {
+ margin-top: 26vh;
+}
+
+.index {
+ text-align: center;
+
+ .title {
+ background: url('../img/searxng.png') no-repeat;
+ min-height: 4rem;
+ margin: 4rem auto;
+ background-position: center;
+ background-size: contain;
+ }
+
+ h1 {
+ font-size: 4em;
+ visibility: hidden;
+ }
+
+ #search,
+ #search_header {
+ margin: 0 auto;
+ background: inherit;
+ border: inherit;
+ padding: 0;
+ display: block;
+ }
+
+ .search_filters {
+ display: block;
+ margin: 1em 0;
+ }
+
+ .category label {
+ padding: 6px 10px;
+ border-bottom: initial !important;
+ }
+}
+
+@media screen and (max-width: @tablet) {
+ div.title {
+ h1 {
+ font-size: 1em;
+ }
+ }
+
+ #main_index {
+ margin-top: 6em;
+ }
+}
diff --git a/searx/static/themes/marlo/src/less/info.less b/searx/static/themes/marlo/src/less/info.less
new file mode 100644
index 000000000..f354135d2
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/info.less
@@ -0,0 +1,10 @@
+.info-page {
+ code {
+ font-family: monospace;
+ .rounded-corners-tiny;
+ background-color: var(--color-doc-code-background);
+ color: var(--color-doc-code);
+ padding: 0.2rem;
+ border: 0 none;
+ }
+}
diff --git a/searx/static/themes/marlo/src/less/mixins.less b/searx/static/themes/marlo/src/less/mixins.less
new file mode 100644
index 000000000..a4bae7128
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/mixins.less
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+// Mixins
+.text-size-adjust (@property: 100%) {
+ -webkit-text-size-adjust: @property;
+ -ms-text-size-adjust: @property;
+ -moz-text-size-adjust: @property;
+ text-size-adjust: @property;
+}
+
+.rounded-corners (@radius: 10px) {
+ border-radius: @radius;
+}
+
+.rounded-right-corners (@radius: 0 10px 10px 0) {
+ border-radius: @radius;
+}
+
+.rounded-corners-tiny (@radius: 5px) {
+ border-radius: @radius;
+}
+
+// disable user selection
+.disable-user-select () {
+ -webkit-touch-callout: none;
+ user-select: none;
+}
+
+.show-content-button() {
+ padding: 5px 10px;
+ .rounded-corners-tiny;
+ background: var(--color-show-btn-background);
+ color: var(--color-show-btn-font);
+ cursor: pointer;
+
+ &:hover {
+ background: var(--color-btn-background);
+ color: var(--color-btn-font);
+ }
+}
diff --git a/searx/static/themes/marlo/src/less/new_issue.less b/searx/static/themes/marlo/src/less/new_issue.less
new file mode 100644
index 000000000..a1e5006e3
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/new_issue.less
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: AGPL-3.0-or-later
+.stats_endpoint {
+ .github-issue-button {
+ display: block;
+ padding: 8px 16px;
+ font-family: sans-serif;
+ font-size: 16px;
+ color: white;
+ background-color: #238636;
+ border: #2ea043;
+ border-radius: 10px !important;
+ box-shadow: rgba(0, 0, 0, 0) 0 0 0 0;
+ }
+
+ .github-issue-button:hover {
+ background-color: #2ea043;
+ }
+
+ .issue-hide {
+ display: none;
+ }
+
+ input[type=checked] {
+ position: absolute;
+ }
+
+ label {
+ margin: 1rem 1rem 1rem 0;
+ }
+
+ .step_content {
+ margin: 1rem 1rem 1rem 2rem;
+ }
+
+ .step1,
+ .step2 {
+ visibility: hidden;
+ }
+
+ .step1_delay {
+ transition: visibility 0s linear 4s;
+ }
+
+ #step1:checked ~ .step1,
+ #step2:checked ~ .step2 {
+ visibility: visible;
+ }
+}
diff --git a/searx/static/themes/marlo/src/less/preferences.less b/searx/static/themes/marlo/src/less/preferences.less
new file mode 100644
index 000000000..ecbcceee7
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/preferences.less
@@ -0,0 +1,225 @@
+table {
+ border-collapse: collapse;
+
+ th,
+ td {
+ text-align: center;
+ padding: 1rem 0.5rem;
+ .ltr-text-align-left();
+ }
+
+ tr.pref-group th {
+ font-weight: normal;
+ .ltr-text-align-left();
+ background: var(--color-settings-table-group-background);
+ }
+}
+
+#main_preferences {
+ form {
+ width: 100%;
+ }
+
+ fieldset {
+ margin: 8px;
+ border: none;
+ }
+
+ legend {
+ margin: 0;
+ padding: 5px 0 0 0;
+ display: block;
+ .ltr-float-left();
+ width: 300px;
+ }
+
+ input[type="text"] {
+ width: 13.25rem;
+ color: var(--color-toolkit-input-text-font);
+ border: none;
+ background: none repeat scroll 0 0 var(--color-toolkit-select-background);
+ padding: 0.2rem 0.4rem;
+ height: 2rem;
+ .rounded-corners-tiny;
+
+ &:hover,
+ &:focus {
+ background-color: var(--color-toolkit-select-background-hover);
+ }
+ }
+
+ .value {
+ margin: 0;
+ padding: 0;
+ .ltr-float-left();
+ width: 15em;
+
+ select,
+ input[type="text"] {
+ font-size: inherit !important;
+ margin-top: 0;
+ .ltr-margin-right(1rem);
+ margin-bottom: 0;
+ .ltr-margin-left(0);
+ }
+
+ select {
+ width: 14rem;
+ }
+
+ select:focus,
+ input:focus {
+ outline: none;
+ box-shadow: 0 0 1px 1px var(--color-btn-background);
+ }
+ }
+
+ .description {
+ margin: 0;
+ padding: 5px 0 0 0;
+ .ltr-float-right();
+ width: 50%;
+ color: var(--color-settings-engine-description-font);
+ font-size: 90%;
+ }
+
+ .bang {
+ .ltr-text-align-left();
+ .rounded-corners-tiny;
+ background-color: var(--color-doc-code-background);
+ color: var(--color-doc-code);
+ padding: 0.2rem;
+ border: 0 none;
+ }
+
+ .category {
+ .ltr-margin-right(0.5rem);
+
+ label {
+ border: 2px solid transparent;
+ padding: 0.2rem 0.4rem;
+ .rounded-corners-tiny;
+ }
+ }
+
+ .category input[type="checkbox"]:checked + label {
+ border: 2px solid var(--color-categories-item-border-selected);
+ }
+
+ table.table_engines {
+ th.name {
+ /* stylelint-disable */
+ label {
+ cursor: pointer;
+ }
+ /* stylelint-enable */
+
+ .engine-tooltip {
+ margin-top: 1.8rem;
+ .ltr-left(calc((100% - 85em) / 2 + 10em));
+ max-width: 40rem;
+
+ .engine-description {
+ margin-top: 0.5rem;
+ }
+
+ .bang {
+ margin: 0.3rem;
+ }
+ }
+ }
+
+ .checkbox-col,
+ .name,
+ .shortcut {
+ .ltr-text-align-left();
+ }
+ }
+
+ table.cookies {
+ width: 100%;
+ direction: ltr;
+
+ th,
+ td {
+ text-align: left;
+ font-family: monospace;
+ font-size: 1rem;
+ padding: 0.5em;
+ vertical-align: top;
+ }
+
+ td:first-child {
+ word-break: keep-all;
+ width: 14rem;
+ padding-right: 1rem;
+ }
+
+ td:last-child {
+ word-break: break-all;
+ }
+
+ & > tbody > tr:nth-child(even) > th,
+ & > tbody > tr:nth-child(even) > td {
+ background-color: var(--color-settings-tr-hover);
+ }
+ }
+
+ .preferences_back {
+ background: none repeat scroll 0 0 var(--color-btn-background);
+ color: var(--color-btn-font);
+ border: 0 none;
+ .rounded-corners;
+
+ cursor: pointer;
+ display: inline-block;
+ margin: 2px 4px;
+ padding: 0.7em;
+
+ a {
+ color: var(--color-settings-return-font);
+ }
+
+ a::first-letter {
+ text-transform: uppercase;
+ }
+ }
+
+ #toggle-all-engines-container {
+ width: max-content;
+ margin-left: auto;
+ }
+
+ div.selectable_url {
+ pre {
+ width: 100%;
+ }
+ }
+
+ #copy-hash-container {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+
+ div.selectable_url {
+ pre {
+ width: auto;
+ flex-grow: 1;
+ }
+ }
+ }
+
+ #pref-hash-input {
+ width: 100%;
+ }
+}
+
+@media screen and (max-width: @tablet) {
+ .preferences_back {
+ clear: both;
+ }
+
+ .engine-tooltip {
+ .ltr-left(10em) !important;
+ }
+}
diff --git a/searx/static/themes/marlo/src/less/result_templates.less b/searx/static/themes/marlo/src/less/result_templates.less
new file mode 100644
index 000000000..afabdf322
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/result_templates.less
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+.osm-map-box {
+ height: 300px;
+ width: 100%;
+ margin: 10px 0;
+}
diff --git a/searx/static/themes/marlo/src/less/search.less b/searx/static/themes/marlo/src/less/search.less
new file mode 100644
index 000000000..f18a7ba2c
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/search.less
@@ -0,0 +1,380 @@
+/*
+* SearXNG, A privacy-respecting, hackable metasearch engine
+*/
+
+#search {
+ padding: 0;
+ margin: 0;
+}
+
+#search_header {
+ padding-top: 1.5em;
+ .ltr-padding-right(2em);
+ .ltr-padding-left(@results-offset - 3rem);
+ margin: 0;
+ background: var(--color-header-background);
+ border-bottom: 1px solid var(--color-header-border);
+ display: grid;
+ column-gap: 1.2rem;
+ row-gap: 1rem;
+ grid-template-columns: 3rem 1fr;
+ grid-template-areas:
+ "logo search"
+ "spacer categories";
+}
+
+.category_checkbox,
+.category_button {
+ display: inline-block;
+ position: relative;
+ .ltr-margin-right(1rem);
+ padding: 0;
+}
+
+.category_checkbox {
+ input {
+ display: none;
+ }
+
+ label {
+ svg {
+ padding-right: 0.2rem;
+ }
+
+ cursor: pointer;
+ padding: 0.2rem 0;
+ display: inline-flex;
+ text-transform: capitalize;
+ font-size: 0.9em;
+ border-bottom: 2px solid transparent;
+ .disable-user-select;
+
+ div.category_name {
+ margin: auto 0;
+ }
+ }
+
+ input[type="checkbox"]:checked + label {
+ color: var(--color-categories-item-selected-font);
+ border-bottom: 2px solid var(--color-categories-item-border-selected);
+ }
+}
+
+button.category_button {
+ background-color: inherit;
+ color: var(--color-base-font);
+ cursor: pointer;
+ padding: 0.2rem 0;
+ display: inline-flex;
+ align-items: center;
+ text-transform: capitalize;
+ font-size: 0.9em;
+ border: none;
+ border-bottom: 2px solid transparent;
+
+ svg {
+ padding-right: 0.2rem;
+ }
+
+ &.selected,
+ &:active,
+ &:focus-within {
+ color: var(--color-categories-item-selected-font);
+ border-bottom: 2px solid var(--color-categories-item-border-selected);
+ }
+}
+
+#categories_container:has(button.category_button:focus-within) button.category_button.selected {
+ color: var(--color-base-font);
+ border-bottom: none;
+}
+
+#search_logo {
+ padding: 0.5rem 10px 0 10px;
+ grid-area: logo;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ svg {
+ flex: 1;
+ width: 30px;
+ height: 30px;
+ margin: 0.5rem 0 auto 0;
+ }
+}
+
+.search_categories {
+ grid-area: categories;
+
+ .help {
+ display: none;
+ }
+
+ &:hover .help {
+ display: block;
+ position: absolute;
+ background: var(--color-base-background);
+ padding: 1rem 0.6rem 0.6rem 0;
+ z-index: 1000;
+ width: 100%;
+ left: -0.1rem;
+ }
+}
+
+#search_view {
+ padding: 0.5rem 0.3rem 0 0.5rem;
+ grid-area: search;
+
+ body.results_endpoint & {
+ padding: 0.5rem 2.8rem 0 0;
+ }
+}
+
+.search_box {
+ border-radius: 0.8rem;
+ width: @search-width;
+ display: inline-flex;
+ flex-direction: row;
+ white-space: nowrap;
+ box-shadow: var(--color-search-shadow);
+}
+
+#clear_search {
+ display: block;
+ border-collapse: separate;
+ box-sizing: border-box;
+ width: 1.8rem;
+ margin: 0;
+ padding: 0.8rem 0.2rem;
+ background: none repeat scroll 0 0 var(--color-search-background);
+ border: none;
+ outline: none;
+ color: var(--color-search-font);
+ font-size: 1.1rem;
+ z-index: 10000;
+
+ &:hover {
+ color: var(--color-search-background-hover);
+ }
+
+ &.empty * {
+ display: none;
+ }
+}
+
+html.no-js #clear_search.hide_if_nojs {
+ display: none;
+}
+
+#q,
+#send_search {
+ display: block;
+ margin: 0;
+ padding: 0.8rem;
+ background: none repeat scroll 0 0 var(--color-search-background);
+ border: none;
+ outline: none;
+ color: var(--color-search-font);
+ font-size: 1.1rem;
+ z-index: 2;
+}
+
+#q {
+ width: 100%;
+ .ltr-padding-left(1rem);
+ .ltr-padding-right(0) !important;
+ .ltr-rounded-left-corners(0.8rem);
+}
+
+#q::-ms-clear,
+#q::-webkit-search-cancel-button {
+ display: none;
+}
+
+#send_search {
+ .ltr-rounded-right-corners(0.8rem);
+
+ &:hover {
+ cursor: pointer;
+ background-color: var(--color-search-background-hover);
+ color: var(--color-search-background);
+ }
+}
+
+.no-js #clear_search,
+.no-js #send_search {
+ width: auto !important;
+ .ltr-border-left(1px solid var(--color-search-border));
+}
+
+.search_filters {
+ margin-top: 0.6rem;
+ .ltr-margin-right(0);
+ margin-bottom: 0;
+ .ltr-margin-left(@results-offset + 0.6rem);
+ display: flex;
+ overflow-x: auto;
+ overscroll-behavior-inline: contain;
+
+ select {
+ background-color: inherit;
+
+ &:hover,
+ &:focus {
+ color: var(--color-base-font);
+ }
+ }
+}
+
+@media screen and (max-width: @tablet) {
+ #search_header {
+ padding: 1.5em @results-tablet-offset 0 @results-tablet-offset;
+ column-gap: @results-tablet-offset;
+ }
+
+ .search_filters {
+ margin-top: 0.6rem;
+ .ltr-margin-right(0);
+ margin-bottom: 0;
+ .ltr-margin-left(@results-tablet-offset + 3rem);
+ }
+
+ #categories {
+ font-size: 90%;
+ clear: both;
+ }
+}
+
+@media screen and (max-width: @tablet) and (hover: none) {
+ #main_index,
+ #main_results {
+ #categories_container {
+ width: max-content;
+
+ .category_checkbox {
+ display: inline-block;
+ width: auto;
+ }
+ }
+
+ #categories {
+ width: 100%;
+ .ltr-text-align-left();
+ overflow-x: scroll;
+ overflow-y: hidden;
+ -webkit-overflow-scrolling: touch;
+ }
+ }
+}
+
+@media screen and (max-width: @phone) {
+ #search_header {
+ width: 100%;
+ margin: 0;
+ padding: 0.1rem 0 0 0;
+ column-gap: 0;
+ row-gap: 0;
+ grid-template-areas:
+ "logo search"
+ "categories categories";
+ }
+
+ .search_logo {
+ padding: 0;
+ }
+
+ .search_box {
+ width: 98%;
+ display: flex;
+ }
+
+ #q {
+ width: 100%;
+ flex: 1;
+ }
+
+ .search_filters {
+ margin: 0 10px;
+ padding: 0.5rem 0;
+ }
+
+ .category {
+ display: inline-block;
+ width: auto;
+ margin: 0;
+
+ svg {
+ display: none;
+ }
+ }
+
+ .category_checkbox {
+ label {
+ padding: 1rem !important;
+ margin: 0 !important;
+ }
+ }
+
+ .category_button {
+ padding: 1rem !important;
+ margin: 0 !important;
+ }
+
+ #search_view:focus-within {
+ display: block;
+ background-color: var(--color-search-background);
+ position: absolute;
+ top: 0;
+ height: 100%;
+ width: 100%;
+ z-index: 10000;
+
+ .search_box {
+ border-bottom: 1px solid var(--color-search-border);
+ width: 100%;
+ border-radius: 0;
+ box-shadow: none;
+
+ #send_search {
+ .ltr-margin-right(0) !important; // Delete when send_search button is disabled on mobile.
+ }
+
+ * {
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ }
+ }
+ }
+
+ #main_results #q:placeholder-shown ~ #send_search {
+ .ltr-margin-right(2.6rem);
+ transition: margin 0.1s;
+ }
+}
+
+@media screen and (max-width: @ultra-small-phone) {
+ #search_header {
+ grid-template-areas:
+ "search search"
+ "categories categories";
+ }
+
+ #search_logo {
+ display: none;
+ }
+}
+
+#categories {
+ .disable-user-select;
+
+ &::-webkit-scrollbar {
+ width: 0;
+ height: 0;
+ }
+}
+
+#categories_container {
+ position: relative;
+}
diff --git a/searx/static/themes/marlo/src/less/stats.less b/searx/static/themes/marlo/src/less/stats.less
new file mode 100644
index 000000000..4658d4f2b
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/stats.less
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+.engine-stats {
+ border-spacing: 0;
+ border-collapse: collapse;
+
+ tr td,
+ tr th {
+ border-bottom: 1px solid var(--color-result-border);
+ padding: 0.25rem;
+ }
+
+ table.engine-tooltip {
+ border-spacing: 0;
+ border-collapse: collapse;
+
+ td,
+ th {
+ border: none;
+ }
+ }
+
+ .engine-name {
+ width: 20rem;
+ }
+
+ .engine-score {
+ width: 7rem;
+ text-align: right;
+ }
+
+ .engine-reliability {
+ text-align: right;
+ }
+}
+
+table.engine-error th.engine-error-type,
+table.engine-error td.engine-error-type,
+failed-test {
+ width: 10rem;
+}
+
+.engine-errors {
+ margin-top: 3rem;
+
+ table.engine-error {
+ max-width: 1280px;
+ margin: 1rem 0 3rem 0;
+ border: 1px solid var(--color-result-border);
+ .ltr-text-align-left();
+
+ tr th,
+ tr td {
+ padding: 0.5rem;
+ }
+
+ & span.log_parameters {
+ border-right: 1px solid solid var(--color-result-border);
+ padding: 0 1rem 0 0;
+ margin: 0 0 0 0.5rem;
+ }
+ }
+}
+
+.bar-chart-value {
+ width: 3em;
+ display: inline-block;
+ text-align: right;
+ padding-right: 0.5rem;
+}
+
+.bar-chart-graph {
+ width: calc(100% - 5rem);
+ display: inline-block;
+}
+
+.bar-chart-bar {
+ border: 3px solid #5bc0de;
+ margin: 1px 0;
+}
+
+.bar-chart-serie1 {
+ border: 3px solid #5bc0de;
+ margin: 1px 0;
+ float: left;
+}
+
+.bar-chart-serie2 {
+ border: 3px solid #deb15b;
+ margin: 1px 0;
+ float: left;
+}
+
+.bar0 {
+ width: 0;
+ border: 0;
+}
+
+.generate-bar(100);
+
+.generate-bar(@n, @i: 1) when (@i =< @n) {
+ .bar@{i} {
+ width: (@i * 100% / @n);
+ }
+ .generate-bar(@n, (@i + 1));
+}
diff --git a/searx/static/themes/marlo/src/less/style-center.less b/searx/static/themes/marlo/src/less/style-center.less
new file mode 100644
index 000000000..30c52cd5a
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/style-center.less
@@ -0,0 +1,118 @@
+/*
+--center-page-width overrides the less variable @results-width when the results are centered
+see the CSS rules for #results in style.less ( grid-template-columns and gap).
+
+In this file, the --center-page-width values comes from the Oscar theme (Bootstrap 3).
+
+All rules starts with ".center-aligment-yes #main_results" to be enabled only
+on the /search URL and when the "center alignment" preference is enabled.
+*/
+
+@media screen and (min-width: @phone) {
+ .center-aligment-yes #main_results {
+ --center-page-width: 48rem;
+ }
+}
+
+@media screen and (min-width: 62rem) {
+ .center-aligment-yes #main_results {
+ --center-page-width: 60rem;
+ }
+}
+
+@media screen and (min-width: @tablet) {
+ .center-aligment-yes #main_results {
+ --center-page-width: 73rem;
+ }
+}
+
+@media screen and (min-width: @phone) and (max-width: @tablet) {
+ // any change must be reset in @media screen and (min-width: @tablet) { ... }
+ .center-aligment-yes #main_results {
+ #results {
+ grid-template-columns: 60% calc(40% - @results-gap);
+ margin-left: 0;
+ margin-right: 0;
+ }
+
+ #urls {
+ .ltr-margin-left(3rem);
+ }
+
+ #sidebar {
+ .ltr-margin-right(1rem);
+ }
+
+ #backToTop {
+ .ltr-left(calc(60% + 1rem));
+ }
+ }
+}
+
+@media screen and (min-width: @tablet) {
+ .center-aligment-yes #main_results {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ #search {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ #search_header {
+ grid-template-columns: calc(50% - 4.5rem - var(--center-page-width) / 2) 3rem var(--center-page-width);
+ grid-template-areas: "na logo search" "na spacer categories";
+ column-gap: 1.2rem; // from search.less
+ width: 100%;
+ padding-left: 0;
+ padding-right: 0;
+ }
+
+ .search_filters {
+ .ltr-margin-left(0.5rem);
+ width: var(--center-page-width);
+ }
+
+ #results {
+ // from style.less (when screen width = @tablet, reset layout from tablet)
+ .ltr-margin-right(2rem);
+ .ltr-margin-left(@results-offset);
+ //
+
+ &.only_template_images,
+ &.image-detail-open {
+ // * grid-template-columns and .ltr-margin-left are set in style.less
+ // * With .image-detail-open.only_template_images, the width is set in detail.less
+ // * #results is going to be centered because of the #main_results rules,
+ // align-self aligns the results on the left or right according to the language.
+ align-self: flex-start;
+ }
+
+ &:not(.only_template_images):not(.image-detail-open) {
+ // the gap is set in style.less
+ .ltr-margin-left(1.5rem);
+ grid-template-columns: calc(var(--center-page-width) - @results-gap - @results-sidebar-width) @results-sidebar-width;
+
+ #backToTop {
+ .ltr-left(calc(50% - @results-sidebar-width - @results-gap + 1rem + var(--center-page-width) / 2));
+ }
+ }
+
+ .result .content {
+ max-width: inherit;
+ }
+ }
+
+ // from style.less (when screen width = @tablet, reset layout from tablet)
+ #urls {
+ .ltr-margin-left(0);
+ }
+
+ #sidebar {
+ .ltr-margin-right(0);
+ }
+ }
+}
diff --git a/searx/static/themes/marlo/src/less/style-ltr.less b/searx/static/themes/marlo/src/less/style-ltr.less
new file mode 100644
index 000000000..6f7218b02
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/style-ltr.less
@@ -0,0 +1,85 @@
+.ltr-left(@offset) {
+ left: @offset;
+}
+
+.ltr-right(@offset) {
+ right: @offset;
+}
+
+.ltr-margin-right(@offset) {
+ margin-right: @offset;
+}
+
+.ltr-margin-left(@offset) {
+ margin-left: @offset;
+}
+
+.ltr-border-right(@offset) {
+ border-right: @offset;
+}
+
+.ltr-border-left(@offset) {
+ border-left: @offset;
+}
+
+.ltr-padding-right(@offset) {
+ padding-right: @offset;
+}
+
+.ltr-padding-left(@offset) {
+ padding-left: @offset;
+}
+
+.ltr-float-left() {
+ float: left;
+}
+
+.ltr-float-right() {
+ float: right;
+}
+
+.ltr-text-align-right() {
+ text-align: right;
+}
+
+.ltr-rounded-left-corners(@radius) {
+ border-radius: @radius 0 0 @radius;
+}
+
+.ltr-rounded-top-left-corners(@radius) {
+ border-radius: @radius 0 0 0;
+}
+
+.ltr-rounded-bottom-left-corners(@radius) {
+ border-radius: 0 0 0 @radius;
+}
+
+.ltr-rounded-right-corners(@radius) {
+ border-radius: 0 @radius @radius 0;
+}
+
+.ltr-rounded-top-right-corners(@radius) {
+ border-radius: 0 @radius 0 0;
+}
+
+.ltr-rounded-bottom-right-corners(@radius) {
+ border-radius: 0 0 @radius 0;
+}
+
+.ltr-text-align-left() {
+ text-align: left;
+}
+
+.ltr-border-left-width(@offset) {
+ border-left-width: @offset;
+}
+
+.ltr-border-right-width(@offset) {
+ border-right-width: @offset;
+}
+
+.ltr-transform() {
+ transform: scale(1, 1);
+}
+
+@import "style.less";
diff --git a/searx/static/themes/marlo/src/less/style-rtl.less b/searx/static/themes/marlo/src/less/style-rtl.less
new file mode 100644
index 000000000..aa97e039c
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/style-rtl.less
@@ -0,0 +1,155 @@
+.ltr-left(@offset) {
+ right: @offset;
+}
+
+.ltr-right(@offset) {
+ left: @offset;
+}
+
+.ltr-margin-right(@offset) {
+ margin-left: @offset;
+}
+
+.ltr-margin-left(@offset) {
+ margin-right: @offset;
+}
+
+.ltr-border-right(@offset) {
+ border-left: @offset;
+}
+
+.ltr-border-left(@offset) {
+ border-right: @offset;
+}
+
+.ltr-padding-right(@offset) {
+ padding-left: @offset;
+}
+
+.ltr-padding-left(@offset) {
+ padding-right: @offset;
+}
+
+.ltr-float-left() {
+ float: right;
+}
+
+.ltr-float-right() {
+ float: left;
+}
+
+.ltr-text-align-right() {
+ text-align: left;
+}
+
+.ltr-rounded-left-corners(@radius) {
+ border-radius: 0 @radius @radius 0;
+}
+
+.ltr-rounded-top-left-corners(@radius) {
+ border-radius: 0 @radius 0 0;
+}
+
+.ltr-rounded-bottom-left-corners(@radius) {
+ border-radius: 0 0 @radius 0;
+}
+
+.ltr-rounded-right-corners(@radius) {
+ border-radius: @radius 0 0 @radius;
+}
+
+.ltr-rounded-top-right-corners(@radius) {
+ border-radius: @radius 0 0 0;
+}
+
+.ltr-rounded-bottom-right-corners(@radius) {
+ border-radius: 0 0 0 @radius;
+}
+
+.ltr-text-align-left() {
+ text-align: right;
+}
+
+.ltr-border-left-width(@offset) {
+ border-right-width: @offset;
+}
+
+.ltr-border-right-width(@offset) {
+ border-left-width: @offset;
+}
+
+.ltr-transform() {
+ transform: scale(-1, 1);
+}
+
+@import "style.less";
+
+#q,
+#sidebar .infobox dt bdi {
+ direction: rtl;
+}
+
+// URL are displayed LTR but align on the right
+#urls {
+ direction: initial;
+ text-align: right;
+
+ .result .url_wrapper {
+ justify-content: end;
+ }
+}
+
+// Image flexbox
+#main_results div#results.only_template_images #urls {
+ direction: rtl;
+}
+
+// Image detail
+#results.image-detail-open article.result-images[data-vim-selected] .detail .result-images-labels p {
+ direction: rtl;
+
+ &.result-url {
+ // Display URL using the LTR direction
+ direction: ltr;
+
+ span {
+ // And put the label on the right
+ direction: rtl;
+ float: right;
+ }
+ }
+}
+
+// select HTML element
+@supports ((background-position-x: 100%) and ((appearance: none) or (-webkit-appearance: none) or (-moz-appearance: none))) {
+ select {
+ border-width: 0 0 0 2rem;
+ background-position-x: -2rem;
+ }
+}
+
+// vim hotkey helps is not translated
+#vim-hotkeys-help table {
+ direction: ltr;
+ text-align: left;
+}
+
+// Logo on the right
+#main_preferences h1,
+#main_stats h1 {
+ background-position-x: 100%;
+}
+
+// patch of stats.less
+.bar-chart-serie1,
+.bar-chart-serie2 {
+ float: right;
+}
+
+.engine-stats .engine-name,
+.engine-stats .engine-score,
+.engine-stats .result-count,
+.engine-stats .response-time,
+.engine-stats .engine-reliability {
+ text-align: right;
+}
diff --git a/searx/static/themes/marlo/src/less/style.less b/searx/static/themes/marlo/src/less/style.less
new file mode 100644
index 000000000..c7f459e59
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/style.less
@@ -0,0 +1,1139 @@
+/*
+* SearXNG, A privacy-respecting, hackable metasearch engine
+*
+* To convert "style.less" to "style.css" run: $make styles
+*/
+
+// stylelint-disable no-descending-specificity
+
+@import (inline) "../../node_modules/normalize.css/normalize.css";
+@import "definitions.less";
+@import "mixins.less";
+@import "code.less";
+@import "toolkit.less";
+@import "autocomplete.less";
+@import "detail.less";
+@import "animations.less";
+@import "embedded.less";
+@import "info.less";
+@import "new_issue.less";
+@import "stats.less";
+@import "result_templates.less";
+
+// for index.html template
+@import "index.less";
+
+// for preferences.html template
+@import "preferences.less";
+
+// Search-Field
+@import "search.less";
+
+// to center the results
+@import "style-center.less";
+
+// ion-icon
+.ion-icon {
+ display: inline-block;
+ vertical-align: bottom;
+ line-height: 1;
+ text-decoration: inherit;
+ .ltr-transform();
+}
+
+.ion-icon-small {
+ width: 1rem;
+ height: 1rem;
+ .ion-icon;
+}
+
+.ion-icon-big {
+ width: 1.5rem;
+ height: 1.5rem;
+ .ion-icon;
+}
+
+// Main LESS-Code
+html {
+ font-family: sans-serif;
+ font-size: 0.9em;
+ .text-size-adjust;
+
+ color: var(--color-base-font);
+ background-color: var(--color-base-background);
+ padding: 0;
+ margin: 0;
+
+ scroll-behavior: smooth;
+}
+
+body,
+main {
+ padding: 0;
+ margin: 0;
+}
+
+body {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ margin: 0;
+}
+
+main {
+ width: 100%;
+ margin-bottom: 2rem;
+ flex: 1;
+}
+
+.page_with_header {
+ margin: 2em auto;
+ width: 85em;
+}
+
+footer {
+ clear: both;
+ min-height: 4rem;
+ padding: 1rem 0;
+ width: 100%;
+ text-align: center;
+ background-color: var(--color-footer-background);
+ border-top: 1px solid var(--color-footer-border);
+ overflow: hidden;
+
+ p {
+ font-size: 0.9em;
+ }
+}
+
+.page_with_header .logo {
+ height: 40px;
+}
+
+input[type="submit"],
+#results button[type="submit"],
+.button {
+ padding: 0.7rem;
+ display: inline-block;
+ background: var(--color-btn-background);
+ color: var(--color-btn-font);
+ .rounded-corners;
+
+ border: 0;
+ cursor: pointer;
+}
+
+a {
+ text-decoration: none;
+ color: var(--color-url-font);
+
+ &:visited {
+ color: var(--color-url-visited-font);
+
+ .highlight {
+ color: var(--color-url-visited-font);
+ }
+ }
+}
+
+article[data-vim-selected] {
+ background: var(--color-result-vim-selected);
+ .ltr-border-left(0.2rem solid var(--color-result-vim-arrow));
+ .ltr-rounded-right-corners(10px);
+}
+
+article.result-images[data-vim-selected] {
+ background: var(--color-result-vim-arrow);
+ border: none;
+ .rounded-corners;
+
+ .image_thumbnail {
+ filter: opacity(60%);
+ }
+
+ span.title,
+ span.source {
+ color: var(--color-result-image-span-font-selected);
+ }
+}
+
+article[data-vim-selected].category-videos,
+article[data-vim-selected].category-news,
+article[data-vim-selected].category-map,
+article[data-vim-selected].category-music,
+article[data-vim-selected].category-files,
+article[data-vim-selected].category-social {
+ border: 1px solid var(--color-result-vim-arrow);
+ .rounded-corners;
+}
+
+.result {
+ margin: @results-margin 0;
+ padding: @result-padding;
+ .ltr-border-left(0.2rem solid transparent);
+
+ h3 {
+ font-size: 1.2rem;
+ word-wrap: break-word;
+ margin: 0.4rem 0 0.4rem 0;
+ padding: 0;
+
+ a {
+ color: var(--color-result-link-font);
+ font-weight: normal;
+ font-size: 1.1em;
+
+ &:visited {
+ color: var(--color-result-link-visited-font);
+ }
+
+ &:focus,
+ &:hover {
+ text-decoration: underline;
+ border: none;
+ outline: none;
+ }
+ }
+ }
+
+ .cache_link,
+ .proxyfied_link {
+ font-size: smaller !important;
+ margin-left: 0.5rem;
+ }
+
+ .content,
+ .stat {
+ font-size: 0.9em;
+ margin: 0;
+ padding: 0;
+ max-width: 54em;
+ word-wrap: break-word;
+ line-height: 1.24;
+
+ .highlight {
+ color: var(--color-result-description-highlight-font);
+ background: inherit;
+ font-weight: bold;
+ }
+ }
+
+ .altlink a {
+ font-size: 0.9em;
+ margin: 0 10px 0 0;
+ .show-content-button;
+ }
+
+ .codelines {
+ .highlight {
+ color: inherit;
+ background: inherit;
+ font-weight: normal;
+ }
+ }
+
+ .url_wrapper {
+ display: flex;
+ font-size: 1rem;
+ color: var(--color-result-url-font);
+ flex-wrap: nowrap;
+ overflow: hidden;
+ flex-direction: row;
+ margin: 0;
+ padding: 0;
+
+ .url_o1 {
+ white-space: nowrap;
+ flex-shrink: 1;
+ }
+
+ .url_o1::after {
+ content: " ";
+ width: 1ch;
+ display: inline-block;
+ }
+
+ .url_o2 {
+ overflow: hidden;
+ white-space: nowrap;
+ flex-basis: content;
+ flex-grow: 0;
+ flex-shrink: 1;
+ text-align: right;
+
+ .url_i2 {
+ float: right;
+ }
+ }
+ }
+
+ .published_date,
+ .result_length,
+ .result_author,
+ .result_shipping,
+ .result_source_country {
+ font-size: 0.8em;
+ color: var(--color-result-publishdate-font);
+ }
+
+ .result_price {
+ font-size: 1.2em;
+ color: var(--color-result-description-highlight-font);
+ }
+
+ img {
+ &.thumbnail {
+ .ltr-float-left();
+ padding-top: 0.6rem;
+ .ltr-padding-right(1rem);
+ width: 20rem;
+ height: unset; // remove heigth value that was needed for lazy loading
+ }
+
+ &.image {
+ .ltr-float-left();
+ padding-top: 0.6rem;
+ .ltr-padding-right(1rem);
+ width: 7rem;
+ max-height: 7rem;
+ object-fit: scale-down;
+ object-position: right top;
+ }
+ }
+
+ .break {
+ clear: both;
+ }
+}
+
+.result-paper,
+.result-packages {
+ .attributes {
+ display: table;
+ border-spacing: 0.125rem;
+
+ div {
+ display: table-row;
+
+ span {
+ font-size: 0.9rem;
+ margin-top: 0.25rem;
+ display: table-cell;
+
+ time {
+ font-size: 0.9rem;
+ }
+ }
+
+ span:first-child {
+ color: var(--color-base-font);
+ min-width: 10rem;
+ }
+
+ span:nth-child(2) {
+ color: var(--color-result-publishdate-font);
+ }
+ }
+ }
+
+ .content {
+ margin-top: 0.25rem;
+ }
+
+ .comments {
+ font-size: 0.9rem;
+ margin: 0.25rem 0 0 0;
+ padding: 0;
+ word-wrap: break-word;
+ line-height: 1.24;
+ font-style: italic;
+ }
+}
+
+.result-packages {
+ .attributes {
+ margin-top: 0.3rem;
+ }
+}
+
+.template_group_images {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.template_group_images::after {
+ flex-grow: 10;
+ content: "";
+}
+
+.category-videos,
+.category-news,
+.category-map,
+.category-music,
+.category-files,
+.category-social {
+ border: 1px solid var(--color-result-border);
+ margin: 0 @results-tablet-offset 1rem @results-tablet-offset !important;
+ .rounded-corners;
+}
+
+.category-social .image {
+ width: auto !important;
+ min-width: 48px;
+ min-height: 48px;
+ padding: 0 5px 25px 0 !important;
+}
+
+.audio-control audio {
+ width: 100%;
+ padding: 10px 0 0 0;
+}
+
+.embedded-content iframe {
+ width: 100%;
+ padding: 10px 0 0 0;
+}
+
+.result-videos .content {
+ overflow: hidden;
+}
+
+.result-videos .embedded-video iframe {
+ width: 100%;
+ aspect-ratio: 16 / 9;
+ padding: 10px 0 0 0;
+}
+
+@supports not (aspect-ratio: 1 / 1) {
+ // support older browsers which do not have aspect-ratio
+ // https://caniuse.com/?search=aspect-ratio
+ .result-videos .embedded-video iframe {
+ height: calc(@results-width * 9 / 16);
+ }
+}
+
+.engines {
+ .ltr-float-right();
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: flex-end;
+ color: var(--color-result-engines-font);
+
+ span {
+ font-size: smaller;
+ margin-top: 0;
+ margin-bottom: 0;
+ .ltr-margin-right(0.5rem);
+ .ltr-margin-left(0);
+ }
+}
+
+.small_font {
+ font-size: 0.8em;
+}
+
+.highlight {
+ color: var(--color-result-link-font-highlight);
+ background: inherit;
+}
+
+.empty_element {
+ font-style: italic;
+}
+
+.result-images {
+ flex-grow: 1;
+ padding: 0.5rem 0.5rem 3rem 0.5rem;
+ margin: 0.25rem;
+ border: none !important;
+ height: @results-image-row-height;
+
+ & > a {
+ position: relative;
+ outline: none;
+ }
+
+ img {
+ margin: 0;
+ padding: 0;
+ border: none;
+ height: 100%;
+ width: 100%;
+ object-fit: cover;
+ vertical-align: bottom;
+ background: var(--color-result-image-background);
+ }
+
+ .image_resolution {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 50%);
+ padding: 0.3rem 0.5rem;
+ font-size: 0.9rem;
+ color: #fff;
+ border-top-left-radius: 0.3rem;
+ }
+
+ span.title,
+ span.source {
+ display: block;
+ position: absolute;
+
+ width: 100%;
+ font-size: 0.9rem;
+ color: var(--color-result-image-span-font);
+ padding: 0.5rem 0 0 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ span.source {
+ padding: 1.8rem 0 0 0;
+ font-size: 0.7rem;
+ }
+}
+
+.result-map {
+ img.image {
+ .ltr-float-right() !important;
+ height: 100px !important;
+ width: auto !important;
+ }
+
+ table {
+ font-size: 0.9em;
+ width: auto;
+ border-collapse: separate;
+ border-spacing: 0 0.35rem;
+
+ th {
+ font-weight: inherit;
+ width: 17rem;
+ vertical-align: top;
+ .ltr-text-align-left();
+ }
+
+ td {
+ vertical-align: top;
+ .ltr-text-align-left();
+ }
+ }
+}
+
+.hidden {
+ display: none !important;
+}
+
+#results {
+ margin-top: 1rem;
+ .ltr-margin-right(2rem);
+ margin-bottom: 0;
+ .ltr-margin-left(@results-offset);
+ display: grid;
+ grid-template-columns: @results-width @results-sidebar-width;
+ grid-template-rows: min-content min-content 1fr min-content;
+ gap: 0 @results-gap;
+ grid-template-areas:
+ "corrections sidebar"
+ "answers sidebar"
+ "urls sidebar"
+ "pagination sidebar";
+}
+
+#results #sidebar *:first-child {
+ margin-top: 0;
+}
+
+#urls {
+ padding: 0;
+ grid-area: urls;
+}
+
+#apis .wrapper {
+ display: flex;
+}
+
+#suggestions {
+ .wrapper {
+ display: flex;
+ flex-flow: column;
+ justify-content: flex-end;
+
+ form {
+ display: inline-block;
+ flex: 1 1 50%;
+ }
+ }
+}
+
+#suggestions,
+#infoboxes {
+ input {
+ padding: 0;
+ margin: 3px;
+ font-size: 0.9em;
+ display: inline-block;
+ background: transparent;
+ color: var(--color-result-search-url-font);
+ cursor: pointer;
+ width: calc(100%);
+ text-overflow: ellipsis;
+ overflow: hidden;
+ text-align: left;
+ }
+
+ input[type="submit"],
+ .infobox .url a {
+ color: var(--color-result-link-font);
+ text-decoration: none;
+ font-size: 0.9rem;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+}
+
+#corrections {
+ grid-area: corrections;
+ display: flex;
+ flex-flow: row wrap;
+ margin: 0 0 1em 0;
+
+ h4,
+ input[type="submit"] {
+ display: inline-block;
+ padding: 0.5rem;
+ margin: 0.5rem;
+ }
+
+ input[type="submit"] {
+ font-size: 0.8rem;
+ .rounded-corners-tiny;
+ }
+}
+
+#infoboxes .title,
+#suggestions .title,
+#search_url .title,
+#engines_msg .title,
+#apis .title {
+ margin: 2em 0 0.5em 0;
+ color: var(--color-base-font);
+}
+
+summary.title {
+ cursor: pointer;
+ padding-top: 1em;
+}
+
+.sidebar-collapsable {
+ border-top: 1px solid var(--color-sidebar-border);
+ padding-bottom: 0.5em;
+}
+
+#sidebar-end-collapsable {
+ border-bottom: 1px solid var(--color-sidebar-border);
+ width: 100%;
+}
+
+#answers {
+ grid-area: answers;
+ background: var(--color-answer-background);
+ padding: @result-padding;
+ margin: 1rem 0;
+ margin-top: 0;
+ color: var(--color-answer-font);
+ .rounded-corners;
+
+ h4 {
+ display: none;
+ }
+
+ span {
+ overflow-wrap: anywhere;
+ }
+
+ .answer {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .answer-url {
+ margin-left: auto;
+ margin-top: 5px;
+ margin-right: 10px;
+ margin-bottom: 10px;
+ }
+}
+
+#infoboxes {
+ form {
+ min-width: 210px;
+ }
+}
+
+#sidebar {
+ grid-area: sidebar;
+ word-wrap: break-word;
+ color: var(--color-sidebar-font);
+
+ .infobox {
+ margin: 10px 0 10px;
+ border: 1px solid var(--color-sidebar-border);
+ padding: 1rem;
+ font-size: 0.9em;
+ .rounded-corners;
+
+ h2 {
+ margin: 0 0 0.5em 0;
+ }
+
+ img {
+ max-width: 100%;
+ max-height: 12em;
+ display: block;
+ margin: 0 auto;
+ padding: 0;
+ }
+
+ dt {
+ font-weight: bold;
+ }
+
+ .attributes {
+ dl {
+ margin: 0.5em 0;
+ }
+
+ dt {
+ display: inline;
+ margin-top: 0.5em;
+ .ltr-margin-right(0.25em);
+ margin-bottom: 0.5em;
+ .ltr-margin-left(0);
+ padding: 0;
+ }
+
+ dd {
+ display: inline;
+ margin: 0.5em 0;
+ padding: 0;
+ }
+ }
+
+ input {
+ font-size: 1em;
+ }
+
+ br {
+ clear: both;
+ }
+
+ .attributes,
+ .urls {
+ clear: both;
+ }
+ }
+}
+
+#apis {
+ input {
+ font-size: 0.9em;
+ margin: 0 10px 0 0;
+ .show-content-button;
+ }
+}
+
+#search_url {
+ div.selectable_url {
+ pre {
+ float: left;
+ width: 200em;
+ }
+ }
+
+ button#copy_url {
+ float: right;
+ padding: 0.4rem;
+ margin-left: 0.5rem;
+ border-radius: 0.3rem;
+ display: none; // will be shown by JS.
+ }
+}
+
+#links_on_top {
+ position: absolute;
+ .ltr-right(1rem);
+ .ltr-text-align-right();
+ top: 2.7rem;
+ padding: 0;
+ border: 0;
+ display: flex;
+ align-items: center;
+ font-size: 1em;
+ color: var(--color-search-font);
+
+ a {
+ display: flex;
+ align-items: center;
+ margin-left: 1em;
+
+ svg {
+ font-size: 1.2em;
+ .ltr-margin-right(0.125em);
+ }
+ }
+
+ a,
+ a:link *,
+ a:hover *,
+ a:visited *,
+ a:active * {
+ color: var(--color-search-font);
+ }
+}
+
+#pagination {
+ grid-area: pagination;
+
+ br {
+ clear: both;
+ }
+}
+
+.numbered_pagination {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ overflow: hidden;
+}
+
+.page_number {
+ background: transparent !important;
+ color: var(--color-result-link-font) !important;
+ text-decoration: underline;
+}
+
+.page_number_current {
+ background: transparent;
+ color: var(--color-result-link-visited-font);
+ border: none;
+}
+
+#backToTop {
+ border: 1px solid var(--color-backtotop-border);
+ margin: 0;
+ padding: 0;
+ font-size: 1em;
+ background: var(--color-backtotop-background);
+ position: fixed;
+ bottom: 8rem;
+ .ltr-left(@results-width + @results-offset + (0.5 * @results-gap - 1.2em));
+ transition: opacity 0.5s;
+ opacity: 0;
+ pointer-events: none;
+ .rounded-corners;
+
+ a {
+ display: block;
+ margin: 0;
+ padding: 0.7em;
+ }
+
+ a,
+ a:visited,
+ a:hover,
+ a:active {
+ color: var(--color-backtotop-font);
+ }
+}
+
+#results.scrolling #backToTop {
+ opacity: 1;
+ pointer-events: all;
+}
+
+/*
+ tablet layout
+*/
+
+.results-tablet() {
+ #links_on_top {
+ span {
+ display: none;
+ }
+ }
+
+ .page_with_header {
+ margin: 2rem 0.5rem;
+ width: auto;
+ }
+
+ #infoboxes {
+ position: inherit;
+ max-width: inherit;
+
+ .infobox {
+ clear: both;
+
+ img {
+ .ltr-float-left();
+ max-width: 10em;
+ margin-top: 0.5em;
+ .ltr-margin-right(0.5em);
+ margin-bottom: 0.5em;
+ .ltr-margin-left(0);
+ }
+ }
+ }
+
+ #sidebar {
+ margin: 0 @results-tablet-offset @results-margin @results-tablet-offset;
+ padding: 0;
+ float: none;
+ border: none;
+ width: auto;
+
+ input {
+ border: 0;
+ }
+ }
+
+ .result {
+ .thumbnail {
+ max-width: 98%;
+ }
+
+ .url {
+ span.url {
+ display: block;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ width: 100%;
+ }
+ }
+
+ .engines {
+ .ltr-float-right();
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: flex-end;
+ padding: 3px 0 0 0;
+ }
+ }
+
+ .result-images {
+ border-bottom: none !important;
+ }
+
+ .image_result {
+ max-width: 98%;
+
+ img {
+ max-width: 98%;
+ }
+ }
+
+ #backToTop {
+ display: none;
+ }
+
+ #pagination {
+ margin: 2rem 0 0 0 !important;
+ }
+
+ #main_results div#results {
+ margin: 0 auto;
+ justify-content: center;
+ display: grid;
+ grid-template-columns: @results-width;
+ grid-template-rows: min-content min-content min-content 1fr min-content min-content;
+ gap: 0;
+ grid-template-areas:
+ "corrections"
+ "answers"
+ "sidebar"
+ "urls"
+ "pagination";
+ }
+}
+
+@media screen and (max-width: calc(@tablet - 0.5px)) {
+ #links_on_top {
+ span {
+ display: none;
+ }
+ }
+}
+
+@media screen and (max-width: 52rem) {
+ body.results_endpoint {
+ #links_on_top {
+ .link_on_top_about,
+ .link_on_top_donate {
+ display: none;
+ }
+ }
+ }
+}
+
+@media screen and (min-width: @phone) and (max-width: @tablet) {
+ // when .center-aligment-yes, see style-center.less
+ // the media query includes "min-width: @phone"
+ // because the phone layout includes the tablet layout unconditionally.
+ .center-aligment-no {
+ .results-tablet();
+ }
+}
+
+/* Misc */
+
+#main_results div#results.only_template_images {
+ margin: 1rem @results-tablet-offset 0 @results-tablet-offset;
+ display: grid;
+ grid-template-columns: 100%;
+ grid-template-rows: min-content min-content min-content 1fr min-content;
+ gap: 0;
+ grid-template-areas:
+ "corrections"
+ "answers"
+ "sidebar"
+ "urls"
+ "pagination";
+
+ #sidebar {
+ display: none;
+ }
+
+ #urls {
+ margin: 0;
+ display: flex;
+ flex-wrap: wrap;
+ }
+
+ #urls::after {
+ flex-grow: 10;
+ content: "";
+ }
+
+ #backToTop {
+ .ltr-left(auto);
+ .ltr-right(1rem);
+ }
+
+ #pagination {
+ .ltr-margin-right(4rem);
+ }
+}
+
+/*
+ phone layout
+*/
+
+@media screen and (max-width: @phone) {
+ // based on the tablet layout
+ .results-tablet();
+
+ html {
+ background-color: var(--color-base-background-mobile);
+ }
+
+ #main_results div#results {
+ grid-template-columns: 100%;
+ margin: 0 auto;
+ }
+
+ #links_on_top {
+ top: 1.4rem;
+ .ltr-right(10px);
+ }
+
+ #main_index #links_on_top {
+ top: 0.5rem;
+ .ltr-right(0.5rem);
+ }
+
+ #results {
+ margin: 0;
+ padding: 0;
+ }
+
+ #pagination {
+ margin: 2rem 1rem 0 1rem !important;
+ }
+
+ article[data-vim-selected] {
+ border: 1px solid var(--color-result-vim-arrow);
+ .rounded-corners;
+ }
+
+ .result {
+ background: var(--color-result-background);
+ border: 1px solid var(--color-result-background);
+ margin: 1rem 10px;
+ .rounded-corners;
+ }
+
+ .result-images {
+ margin: 0;
+ height: @results-image-row-height-phone;
+ background: var(--color-base-background-mobile);
+ }
+
+ .infobox {
+ border: none !important;
+ background-color: var(--color-sidebar-background);
+ }
+
+ .numbered_pagination {
+ display: none;
+ }
+
+ .result-paper,
+ .result-packages {
+ .attributes {
+ display: block;
+
+ div {
+ display: block;
+
+ span {
+ display: inline;
+ }
+
+ span:first-child {
+ font-weight: bold;
+ }
+
+ span:nth-child(2) {
+ .ltr-margin-left(0.5rem);
+ }
+ }
+ }
+ }
+}
+
+/*
+ small-phone layout
+*/
+
+@media screen and (max-width: @small-phone) {
+ .result-videos {
+ img.thumbnail {
+ float: none !important;
+ }
+
+ .content {
+ overflow: inherit;
+ }
+ }
+}
+
+pre code {
+ white-space: pre-wrap;
+}
diff --git a/searx/static/themes/marlo/src/less/toolkit.less b/searx/static/themes/marlo/src/less/toolkit.less
new file mode 100644
index 000000000..f4e3c36e1
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/toolkit.less
@@ -0,0 +1,648 @@
+// other solution : http://stackoverflow.com/questions/1577598/how-to-hide-parts-of-html-when-javascript-is-disabled/13857783#13857783
+
+// stylelint-disable no-descending-specificity
+
+html.no-js .hide_if_nojs {
+ display: none;
+}
+
+html.js .show_if_nojs {
+ display: none;
+}
+
+.center {
+ text-align: center;
+}
+
+.right {
+ float: right;
+}
+
+.left {
+ float: left;
+}
+
+.invisible {
+ display: none !important;
+}
+
+.list-unstyled {
+ list-style-type: none;
+
+ li {
+ margin-top: 4px;
+ margin-bottom: 4px;
+ }
+}
+
+.danger {
+ background-color: var(--color-error-background);
+}
+
+.warning {
+ background: var(--color-warning-background);
+}
+
+.success {
+ background: var(--color-success-background);
+}
+
+.badge {
+ display: inline-block;
+ color: var(--color-toolkit-badge-font);
+ background-color: var(--color-toolkit-badge-background);
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ min-width: 10px;
+ padding: 1px 5px;
+ border-radius: 5px;
+}
+
+// kbd
+kbd {
+ padding: 2px 4px;
+ margin: 1px;
+ font-size: 90%;
+ color: var(--color-toolkit-kbd-font);
+ background: var(--color-toolkit-kbd-background);
+}
+
+// table
+table {
+ width: 100%;
+
+ &.striped {
+ tr {
+ border-bottom: 1px solid var(--color-settings-tr-hover);
+ }
+ }
+}
+
+th {
+ padding: 0.4em;
+}
+
+td {
+ padding: 0 4px;
+}
+
+tr {
+ &:hover {
+ background: var(--color-settings-tr-hover) !important;
+ }
+}
+
+// pre
+.pre() {
+ display: block;
+ font-size: 0.8em;
+ word-break: break-all;
+ margin: 0.1em;
+ user-select: all;
+}
+
+div.selectable_url {
+ display: block;
+ border: 1px solid var(--color-result-search-url-border);
+ padding: 4px;
+ color: var(--color-result-search-url-font);
+ margin: 0.1em;
+ overflow: hidden;
+ height: 1.2em;
+ line-height: 1.2em;
+ .rounded-corners-tiny;
+
+ pre {
+ .pre();
+ }
+}
+
+// dialog
+.dialog() {
+ position: relative;
+ display: flex;
+ padding: 1rem;
+ margin: 0 0 1em 0;
+ border: 1px solid var(--color-toolkit-dialog-border);
+ .ltr-text-align-left();
+ .rounded-corners;
+
+ .close {
+ .ltr-float-right();
+ position: relative;
+ top: -3px;
+ color: inherit;
+ font-size: 1.5em;
+ }
+
+ ul,
+ ol,
+ p {
+ margin: 1px 0 0 0;
+ }
+
+ table {
+ width: auto;
+ }
+
+ tr {
+ vertical-align: text-top;
+
+ &:hover {
+ background: transparent !important;
+ }
+ }
+
+ td {
+ padding: 0 1em 0 0;
+ padding-top: 0;
+ .ltr-padding-right(1rem);
+ padding-bottom: 0;
+ .ltr-padding-left(0);
+ }
+
+ h4 {
+ margin-top: 0.3em;
+ margin-bottom: 0.3em;
+ }
+}
+
+.dialog-error {
+ .dialog();
+
+ color: var(--color-error);
+ background: var(--color-error-background);
+ border-color: var(--color-error);
+}
+
+.dialog-error-block {
+ .dialog();
+
+ display: block;
+ color: var(--color-error);
+ background: var(--color-error-background);
+ border-color: var(--color-error);
+}
+
+.dialog-warning {
+ .dialog();
+
+ color: var(--color-warning);
+ background: var(--color-warning-background);
+ border-color: var(--color-warning);
+}
+
+.dialog-modal {
+ .dialog();
+
+ display: block;
+ background: var(--color-toolkit-dialog-background);
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin: 0 auto;
+ transform: translate(-50%, -50%);
+ z-index: 10000000;
+
+ h3 {
+ margin-top: 0;
+ }
+}
+
+// btn-collapse
+.btn-collapse {
+ cursor: pointer;
+}
+
+//
+.scrollx {
+ overflow-x: auto;
+ overflow-y: hidden;
+ display: block;
+ padding: 0;
+ margin: 0;
+ border: none;
+}
+
+/* -- tabs -- */
+.tabs .tabs > label {
+ font-size: 90%;
+}
+
+ul.tabs {
+ border-bottom: 1px solid var(--color-toolkit-tabs-section-border);
+ list-style: none;
+ padding-left: 0;
+
+ li {
+ display: flex;
+ }
+}
+
+.tabs {
+ display: flex;
+ flex-wrap: wrap;
+ width: 100%;
+ min-width: 100%;
+
+ & > * {
+ order: 2;
+ }
+
+ & > input[type=radio] {
+ display: none;
+ }
+
+ & > label,
+ & > li > a {
+ order: 1;
+ padding: 0.7em;
+ margin: 0 0.7em;
+ letter-spacing: 0.5px;
+ text-transform: uppercase;
+ border: solid var(--color-toolkit-tabs-label-border);
+ border-width: 0 0 2px 0;
+ color: unset;
+
+ .disable-user-select();
+
+ cursor: pointer;
+
+ &.active {
+ border-bottom: 2px solid var(--color-categories-item-border-selected);
+ background: var(--color-categories-item-selected);
+ color: var(--color-categories-item-selected-font);
+ }
+ }
+
+ & > label:hover,
+ & > li > a:hover {
+ border-bottom: 2px solid var(--color-categories-item-border-selected);
+ }
+
+ & > section {
+ min-width: 100%;
+ padding: 0.7rem 0;
+ box-sizing: border-box;
+ border-top: 1px solid var(--color-toolkit-tabs-section-border);
+ display: none;
+ }
+
+ // default selection
+ & > label:last-of-type {
+ border-bottom: 2px solid var(--color-categories-item-border-selected);
+ background: var(--color-categories-item-selected);
+ color: var(--color-categories-item-selected-font);
+ letter-spacing: -0.1px;
+ }
+
+ & > section:last-of-type {
+ display: block;
+ }
+}
+
+html body .tabs > input:checked {
+ ~ section {
+ display: none;
+ }
+
+ ~ label {
+ position: inherited;
+ background: inherit;
+ border-bottom: 2px solid transparent;
+ font-weight: normal;
+ color: inherit;
+
+ &:hover {
+ border-bottom: 2px solid var(--color-categories-item-border-selected);
+ }
+ }
+
+ + label {
+ border-bottom: 2px solid var(--color-categories-item-border-selected);
+ background: var(--color-categories-item-selected);
+ color: var(--color-categories-item-selected-font);
+ }
+
+ + label + section {
+ display: block;
+ }
+}
+
+/* -- select -- */
+select {
+ height: 2.4rem;
+ margin-top: 0;
+ .ltr-margin-right(1rem);
+ margin-bottom: 0;
+ .ltr-margin-left(0);
+ padding: 0.2rem !important;
+ color: var(--color-search-font);
+ font-size: 0.9rem;
+ z-index: 2;
+
+ &:hover,
+ &:focus {
+ cursor: pointer;
+ }
+}
+
+@supports ((background-position-x: 100%) and ((appearance: none) or (-webkit-appearance: none) or (-moz-appearance: none))) {
+ select {
+ appearance: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ border-width: 0 2rem 0 0;
+ border-color: transparent;
+ background: data-uri('image/svg+xml;charset=UTF-8', @select-light-svg-path) no-repeat;
+ background-position-x: calc(100% + 2rem);
+ background-size: 2rem;
+ background-origin: content-box;
+ background-color: var(--color-toolkit-select-background);
+ outline: medium none;
+ text-overflow: ellipsis;
+ .rounded-corners-tiny;
+
+ &:hover,
+ &:focus {
+ background-color: var(--color-toolkit-select-background-hover);
+ }
+
+ option {
+ background-color: var(--color-base-background);
+ }
+ }
+
+ @media (prefers-color-scheme: dark) {
+ html.theme-auto select,
+ html.theme-dark select {
+ background-image: data-uri('image/svg+xml;charset=UTF-8', @select-dark-svg-path);
+ }
+ }
+
+ html.theme-dark select {
+ background-image: data-uri('image/svg+xml;charset=UTF-8', @select-dark-svg-path);
+ }
+}
+
+/* -- checkbox-onoff -- */
+input.checkbox-onoff[type="checkbox"] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ cursor: pointer;
+ display: inline-block;
+ width: 2.5em;
+ height: 0.7em;
+ box-shadow: none !important;
+ margin: 0 16px;
+ border-radius: 10px;
+ position: relative;
+
+ /* focus & hover */
+ &:focus,
+ &:hover {
+ outline: none;
+ }
+
+ &:focus::after {
+ content: "";
+ position: absolute;
+ width: 3.5em;
+ height: 1.65em;
+ border: 1px solid var(--color-btn-background);
+ border-radius: 12px;
+ box-shadow: var(--color-btn-background) 0 0 3px;
+ z-index: 10000;
+ top: -0.55em;
+ left: -0.6em;
+ }
+
+ &::before {
+ position: absolute;
+ top: -0.5em;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 0.75em;
+ width: 1.875em;
+ height: 1.875em;
+ border-radius: 50%;
+ }
+}
+
+/* check mark
+reversed-checkbox displays unchecked checkedboxes as checked, and vice versa.
+see https://github.com/searxng/searxng/blob/3408d061aab9abc6168fec9bbc6deab71b236dac/searx/templates/simple/preferences.html#L313
+*/
+input.checkbox-onoff[type="checkbox"],
+input.checkbox-onoff.reversed-checkbox[type="checkbox"]:checked {
+ background: var(--color-toolkit-checkbox-onoff-off-background);
+
+ &::before {
+ left: -0.5em;
+ content: "\2715";
+ color: var(--color-toolkit-checkbox-onoff-off-mark-color);
+ background: var(--color-toolkit-checkbox-onoff-off-mark-background);
+ }
+}
+
+input.checkbox-onoff[type="checkbox"]:checked,
+input.checkbox-onoff.reversed-checkbox[type="checkbox"] {
+ background: var(--color-toolkit-checkbox-onoff-on-background);
+
+ &::before {
+ left: calc(100% - 1.5em);
+ content: "\2713";
+ color: var(--color-toolkit-checkbox-onoff-on-mark-color);
+ background: var(--color-toolkit-checkbox-onoff-on-mark-background);
+ }
+}
+
+/* -- checkbox -- */
+@supports (transform: rotate(-45deg)) {
+ input[type=checkbox]:not(.checkbox-onoff) {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ width: 20px;
+ height: 20px;
+ cursor: pointer;
+ position: relative;
+ top: 0;
+ left: 0;
+ border: 2px solid var(--color-toolkit-checkbox-input-border);
+ .rounded-corners(0.3em);
+
+ &::after {
+ content: '';
+ width: 9px;
+ height: 5px;
+ position: absolute;
+ top: 3px;
+ left: 2px;
+ border: 3px solid var(--color-toolkit-checkbox-label-border);
+ border-top: none;
+ border-right: none;
+ background: transparent;
+ opacity: 0;
+ transform: rotate(-45deg);
+ }
+
+ &:checked::after {
+ border-color: var(--color-toolkit-checkbox-input-border);
+ opacity: 1;
+ }
+ }
+
+ // disabled : can't be focused, show only the check mark
+ input[type=checkbox][disabled]:not(.checkbox-onoff) {
+ border: inherit;
+ background-color: transparent !important;
+ cursor: inherit;
+ }
+
+ // if not checked and possible to checked then display a "light" check mark on hover
+ input.checkbox[type=checkbox]:not(:checked):not([disabled]):not(.checkbox-onoff):hover::after {
+ opacity: 0.5;
+ }
+}
+
+@media screen and (max-width: @phone) {
+ .tabs > label {
+ width: 100%;
+ }
+}
+
+/* -- loader -- */
+.loader,
+.loader::after {
+ border-radius: 50%;
+ width: 2em;
+ height: 2em;
+}
+
+.loader {
+ margin: 1em auto;
+ font-size: 10px;
+ position: relative;
+ text-indent: -9999em;
+ border-top: 0.5em solid var(--color-toolkit-loader-border);
+ border-right: 0.5em solid var(--color-toolkit-loader-border);
+ border-bottom: 0.5em solid var(--color-toolkit-loader-border);
+ border-left: 0.5em solid var(--color-toolkit-loader-borderleft);
+ -webkit-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+ -webkit-animation: load8 1.2s infinite linear;
+ animation: load8 1.2s infinite linear;
+}
+
+@-webkit-keyframes load8 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes load8 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+/* -- engine-tooltip -- */
+.engine-tooltip {
+ display: none;
+ position: absolute;
+ padding: 0.5rem 1rem;
+ margin: 0 0 0 2rem;
+ border: 1px solid var(--color-toolkit-engine-tooltip-border);
+ background: var(--color-toolkit-engine-tooltip-background);
+ font-size: 14px;
+ font-weight: normal;
+ z-index: 1000000;
+ text-align: left;
+ .rounded-corners;
+}
+
+th:hover .engine-tooltip,
+td:hover .engine-tooltip,
+.engine-tooltip:hover {
+ display: inline-block;
+}
+
+/* -- stacked bar chart -- */
+.stacked-bar-chart {
+ margin: 0;
+ padding: 0 0.125rem 0 4rem;
+ width: 100%;
+ width: -moz-available;
+ width: -webkit-fill-available;
+ width: fill;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ align-items: center;
+ display: inline-flex;
+}
+
+.stacked-bar-chart-value {
+ width: 3rem;
+ display: inline-block;
+ position: absolute;
+ padding: 0 0.5rem;
+ text-align: right;
+}
+
+.stacked-bar-chart-base {
+ display: flex;
+ flex-shrink: 0;
+ flex-grow: 0;
+ flex-basis: unset;
+}
+
+.stacked-bar-chart-median {
+ .stacked-bar-chart-base();
+
+ background: var(--color-base-font);
+ border: 1px solid rgba(var(--color-base-font-rgb), 0.9);
+ padding: 0.3rem 0;
+}
+
+.stacked-bar-chart-rate80 {
+ .stacked-bar-chart-base();
+
+ background: transparent;
+ border: 1px solid rgba(var(--color-base-font-rgb), 0.3);
+ padding: 0.3rem 0;
+}
+
+.stacked-bar-chart-rate95 {
+ .stacked-bar-chart-base();
+
+ background: transparent;
+ border-bottom: 1px dotted rgba(var(--color-base-font-rgb), 0.5);
+ padding: 0;
+}
+
+.stacked-bar-chart-rate100 {
+ .stacked-bar-chart-base();
+
+ background: transparent;
+ border-left: 1px solid rgba(var(--color-base-font-rgb), 0.9);
+ padding: 0.4rem 0;
+ width: 1px;
+}
diff --git a/searx/static/themes/marlo/src/less/toolkit_loader.less b/searx/static/themes/marlo/src/less/toolkit_loader.less
new file mode 100644
index 000000000..d426035a3
--- /dev/null
+++ b/searx/static/themes/marlo/src/less/toolkit_loader.less
@@ -0,0 +1,46 @@
+.loader,
+.loader::after {
+ border-radius: 50%;
+ width: 10em;
+ height: 10em;
+}
+
+.loader {
+ margin: 60px auto;
+ font-size: 10px;
+ position: relative;
+ text-indent: -9999em;
+ border-top: 1.1em solid rgba(255, 255, 255, 0.2);
+ border-right: 1.1em solid rgba(255, 255, 255, 0.2);
+ border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
+ border-left: 1.1em solid #fff;
+ -webkit-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+ -webkit-animation: load8 1.1s infinite linear;
+ animation: load8 1.1s infinite linear;
+}
+
+@-webkit-keyframes load8 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes load8 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
diff --git a/searx/static/themes/marlo/src/svg/information-circle-outline.svg b/searx/static/themes/marlo/src/svg/information-circle-outline.svg
new file mode 100644
index 000000000..b7c300094
--- /dev/null
+++ b/searx/static/themes/marlo/src/svg/information-circle-outline.svg
@@ -0,0 +1,6 @@
+
+ Information Circle
+
+
+
+
\ No newline at end of file
diff --git a/searx/static/themes/marlo/src/svg/select-dark.svg b/searx/static/themes/marlo/src/svg/select-dark.svg
new file mode 100644
index 000000000..97335cea5
--- /dev/null
+++ b/searx/static/themes/marlo/src/svg/select-dark.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/searx/static/themes/marlo/src/svg/select-light.svg b/searx/static/themes/marlo/src/svg/select-light.svg
new file mode 100644
index 000000000..3b707f018
--- /dev/null
+++ b/searx/static/themes/marlo/src/svg/select-light.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/searx/static/themes/marlo/svg4favicon.svgo.js b/searx/static/themes/marlo/svg4favicon.svgo.js
new file mode 100644
index 000000000..b9dd0da8e
--- /dev/null
+++ b/searx/static/themes/marlo/svg4favicon.svgo.js
@@ -0,0 +1,16 @@
+/**
+ * @license
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ *
+ * svgo config: Optimize SVG for WEB usage
+ */
+
+module.exports = {
+ plugins: [
+ {
+ name: 'preset-default',
+ },
+ // make diff friendly
+ 'sortAttrs',
+ ],
+};
diff --git a/searx/static/themes/marlo/svg4web.svgo.js b/searx/static/themes/marlo/svg4web.svgo.js
new file mode 100644
index 000000000..83f74cde1
--- /dev/null
+++ b/searx/static/themes/marlo/svg4web.svgo.js
@@ -0,0 +1,19 @@
+/**
+ * @license
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ *
+ * svgo config: Optimize SVG for WEB usage
+ */
+
+module.exports = {
+ plugins: [
+ {
+ name: 'preset-default',
+ },
+ // make diff friendly
+ 'sortAttrs',
+ // Optimize SVG for WEB usage
+ 'convertStyleToAttrs',
+ 'removeXMLNS'
+ ],
+};