diff --git a/index.html b/index.html new file mode 100644 index 0000000..2c39f2e --- /dev/null +++ b/index.html @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+
+ +
+
+
+ + + + +
+
+
+ +
+ +
+
+
+
+ + + +
+ +
+ +
+
Lang 1
+
Lang 2
+
Lang 3
+
Lang 4
+
Lang 5
+
Lang 6
+
Lang 7
+
Lang 8
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
Swipe Up To Unlock
+
+ +
+
+
+
+

Control Center

+ + + + +
+
+
+
+
Title
+
Author
+
+ + + +
+
+
+ +
+
+
+
    +
  • +
  • +
  • +
  • +
  • +
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+

Notifications

+ + + + +
+
    +
    +
    +
    + +
    +
    + +
    App Name
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + +
    +
    + + +
    +
    + +
    + + +
    + + +
    +
    + +
    + + + + + +
    +
    +
    + + \ No newline at end of file diff --git a/js/app_window.js b/js/app_window.js new file mode 100644 index 0000000..a4a74a1 --- /dev/null +++ b/js/app_window.js @@ -0,0 +1,241 @@ +const AppWindow = { + _id: 0, + + containerElement: document.getElementById('windows'), + statusbar: document.getElementById('statusbar'), + softwareButtons: document.getElementById('software-buttons'), + softwareBackButton: document.getElementById('software-back-button'), + softwareHomeButton: document.getElementById('software-home-button'), + dock: document.getElementById('dock'), + + HIDDEN_ROLES: [ 'system', 'homescreen' ], + + init: function () { + this.softwareBackButton.addEventListener('click', this.onButtonClick.bind(this)); + this.softwareHomeButton.addEventListener('click', this.onButtonClick.bind(this)); + }, + + create: async function (manifestUrl, options) { + var existingWindow = this.containerElement.querySelector(`[data-manifest-url="${manifestUrl}"]`); + if (existingWindow) { + if (options.originPos) { + if (this.homescreenElement) { + this.homescreenElement.style.transformOrigin = `${options.originPos.x}px ${options.originPos.y}px`; + } + existingWindow.style.transformOrigin = `${options.originPos.x}px ${options.originPos.y}px`; + } + this.unminimize(existingWindow.id); + return; + } + + const windowId = `appframe${AppWindow._id}`; + console.log(windowId + ': ' + manifestUrl); + AppWindow._id++; + + var manifest; + await fetch(manifestUrl) + .then(response => response.json()) + .then(function (data) { + manifest = data; + // You can perform further operations with the 'manifest' variable here + }) + .catch(function (error) { + console.log('Error fetching manifest:', error); + }); + + // Apply window options + const windowOptions = Object.assign( + { + start_url: manifest.start_url, + launch_path: manifest.launch_path, + width: manifest.width, + height: manifest.height, + transparent: manifest.transparent, + cli_args: '' + }, + options + ); + + // Create dock icon + if (this.HIDDEN_ROLES.indexOf(manifest.role) == -1) { + const icon = document.createElement('div'); + icon.classList.add('icon'); + icon.dataset.manifestUrl = manifestUrl; + icon.onclick = () => { + this.focus(windowId); + }; + this.dock.appendChild(icon); + + icon.classList.add('expand'); + icon.addEventListener('animationend', () => { + icon.classList.remove('expand'); + }); + + const iconImage = document.createElement('img'); + Object.entries(manifest.icons).forEach(entry => { + if (entry[0] >= this.DOCK_ICON_SIZE) { + return; + } + const url = new URL(manifestUrl); + iconImage.src = url.origin + entry[1]; + }); + icon.appendChild(iconImage); + } + + // Create window container + const windowDiv = document.createElement('div'); + windowDiv.dataset.manifestUrl = manifestUrl; + if (manifest.role == 'homescreen') { + windowDiv.id = 'homescreen'; + AppWindow.homescreenElement = windowDiv; + } else { + windowDiv.id = windowId; + } + windowDiv.classList.add('appframe'); + if (manifest.statusbar && manifest.statusbar !== 'normal') { + windowDiv.classList.add(manifest.statusbar); + } + if (manifest.display && manifest.display !== 'standalone') { + windowDiv.classList.add(manifest.display); + } + if (windowOptions.transparent) { + windowDiv.classList.add('transparent'); + } + if (windowOptions.originPos) { + if (this.homescreenElement) { + this.homescreenElement.style.transformOrigin = `${windowOptions.originPos.x}px ${windowOptions.originPos.y}px`; + } + windowDiv.style.transformOrigin = `${windowOptions.originPos.x}px ${windowOptions.originPos.y}px`; + } + this.containerElement.appendChild(windowDiv); + + // Focus the app window + this.focus(windowDiv.id); + + windowDiv.classList.add('expand'); + windowDiv.addEventListener('animationend', () => { + windowDiv.classList.remove('expand'); + }); + + // Create chrome + var chromeContainer = document.createElement('div'); + chromeContainer.classList.add('chrome'); + windowDiv.appendChild(chromeContainer); + + var isChromeEnabled = false; + if (manifest.chrome && manifest.chrome.navigation) { + isChromeEnabled = true; + } + + if (manifest.start_url) { + Browser.init(chromeContainer, manifest.start_url, isChromeEnabled); + } else { + if (manifest.launch_path) { + var url = new URL(manifestUrl); + Browser.init(chromeContainer, url.origin + manifest.launch_path, isChromeEnabled); + } + } + }, + + focus: function (id) { + var windowDiv = document.getElementById(id); + var manifestUrl = windowDiv.dataset.manifestUrl; + var dockIcon = this.dock.querySelector(`[data-manifest-url="${manifestUrl}"]`); + + this.containerElement.querySelectorAll('.appframe').forEach((element) => { + element.classList.remove('active'); + }); + this.dock.querySelectorAll('.icon').forEach((element) => { + element.classList.remove('active'); + }); + + windowDiv.classList.add('active'); + if (dockIcon) { + dockIcon.classList.add('active'); + } + this.focusedWindow = windowDiv; + }, + + close: function (id) { + if (id === 'homescreen') { + return; + } + var windowDiv = document.getElementById(id); + var manifestUrl = windowDiv.dataset.manifestUrl; + var dockIcon = this.dock.querySelector(`[data-manifest-url="${manifestUrl}"]`); + + windowDiv.classList.add('shrink'); + if (dockIcon) { + dockIcon.classList.add('shrink'); + } + windowDiv.addEventListener('animationend', () => { + windowDiv.classList.remove('shrink'); + windowDiv.remove(); + if (dockIcon) { + dockIcon.classList.remove('shrink'); + dockIcon.remove(); + } + this.focus('homescreen'); + }); + }, + + minimize: function (id) { + if (id === 'homescreen') { + return; + } + var windowDiv = document.getElementById(id); + var manifestUrl = windowDiv.dataset.manifestUrl; + var dockIcon = this.dock.querySelector(`[data-manifest-url="${manifestUrl}"]`); + + windowDiv.classList.add('shrink'); + if (dockIcon) { + dockIcon.classList.add('minimized'); + } + windowDiv.addEventListener('animationend', () => { + windowDiv.classList.remove('active'); + windowDiv.classList.remove('shrink'); + this.focus('homescreen'); + }); + }, + + unminimize: function (id) { + if (id === 'homescreen') { + return; + } + var windowDiv = document.getElementById(id); + var manifestUrl = windowDiv.dataset.manifestUrl; + var dockIcon = this.dock.querySelector(`[data-manifest-url="${manifestUrl}"]`); + + windowDiv.classList.add('active'); + windowDiv.classList.add('expand'); + if (dockIcon) { + dockIcon.classList.remove('minimized'); + } + windowDiv.addEventListener('animationend', () => { + windowDiv.classList.remove('expand'); + this.focus(id); + }); + }, + + onButtonClick: function (event) { + switch (event.target) { + case this.softwareBackButton: + var webview = this.focusedWindow.querySelector('.browser.active'); + if (webview.canGoBack()) { + webview.goBack(); + } else { + this.close(this.focusedWindow.id); + } + break; + + case this.softwareHomeButton: + this.minimize(this.focusedWindow.id); + break; + + default: + break; + } + }, +}; + +AppWindow.init(); diff --git a/js/battery_icon.js b/js/battery_icon.js new file mode 100644 index 0000000..2eebc83 --- /dev/null +++ b/js/battery_icon.js @@ -0,0 +1,33 @@ +const BatteryIcon = { + iconElement: document.getElementById("statusbar-battery"), + + init: function () { + navigator.getBattery().then((battery) => { + this.battery = battery; + + this.iconElement.classList.remove("hidden"); + + var level = battery.level; + var charging = battery.charging; + if (charging) { + this.iconElement.dataset.icon = `battery-charging-${Math.round(level * 10) * 10}`; + } else { + this.iconElement.dataset.icon = `battery-${Math.round(level * 10) * 10}`; + } + + ['chargingchange', 'dischargingchange', 'levelchange'].forEach(event => { + battery.addEventListener(event, () => { + level = battery.level; + charging = battery.isCharging; + if (charging) { + this.iconElement.dataset.icon = `battery-charging-${Math.round(level * 10) * 10}`; + } else { + this.iconElement.dataset.icon = `battery-${Math.round(level * 10) * 10}`; + } + }); + }); + }); + } +} + +BatteryIcon.init(); diff --git a/js/bletooth_icon.js b/js/bletooth_icon.js new file mode 100644 index 0000000..365003c --- /dev/null +++ b/js/bletooth_icon.js @@ -0,0 +1,32 @@ + +const BluetoothIcon = { + iconElement: document.getElementById("statusbar-bluetooth"), + + init: function () { + this.update(); + }, + + update: function () { + si.bluetoothDevices((err, data) => { + if (err) { + console.error(err); + } else { + const connectedBluetooth = networks.find(network => network.state === 'connected'); + + const bluetoothEnabled = (connectedBluetooth) || false; + console.log("Bluetooth Enabled:", bluetoothEnabled); + + if (bluetoothEnabled) { + this.iconElement.classList.remove("hidden"); + } else { + this.iconElement.classList.add("hidden"); + } + } + }); + + clearTimeout(this.timer); + this.timer = setTimeout(this.update, 1000); + }, +}; + +BluetoothIcon.init(); diff --git a/js/bootstrap.js b/js/bootstrap.js new file mode 100644 index 0000000..6600e2d --- /dev/null +++ b/js/bootstrap.js @@ -0,0 +1,8 @@ +const path = require('path'); +const si = require("systeminformation"); + +document.addEventListener('DOMContentLoaded', function () { + if (document.readyState === "complete") {} + + AppWindow.create('http://homescreen.localhost:8081/manifest.json'); +}); diff --git a/js/browser/browser.js b/js/browser/browser.js new file mode 100644 index 0000000..e69de29 diff --git a/js/chrome.js b/js/chrome.js new file mode 100644 index 0000000..a0e990a --- /dev/null +++ b/js/chrome.js @@ -0,0 +1,330 @@ +const Browser = { + chrome: document.getElementById('chrome'), + DEFAULT_URL: 'https://www.duckduckgo.com', + + tablist: function() { + return this.chrome.querySelector('.tablist'); + }, + + addButton: function() { + return this.chrome.querySelector('.add-button'); + }, + + navbarBackButton: function() { + return this.chrome.querySelector('.navbar-back-button'); + }, + + navbarForwardButton: function() { + return this.chrome.querySelector('.navbar-forward-button'); + }, + + navbarReloadButton: function() { + return this.chrome.querySelector('.navbar-reload-button'); + }, + + navbarHomeButton: function() { + return this.chrome.querySelector('.navbar-home-button'); + }, + + urlbar: function() { + return this.chrome.querySelector('.urlbar'); + }, + + urlbarInput: function() { + return this.chrome.querySelector('.urlbar-input'); + }, + + urlbarDisplayUrl: function() { + return this.chrome.querySelector('.urlbar-display-url'); + }, + + browserContainer: function() { + return this.chrome.querySelector('.browser-container'); + }, + + init: function(chromeElement, url, isChromeEnabled) { + if (chromeElement) { + this.chrome = chromeElement; + this.chrome.innerHTML = ` +
    +
    + + + + +
    + +
    +
    + `; + } + if (isChromeEnabled) { + this.chrome.classList.add('visible'); + } + this.openNewTab(false, url); + + this.addButton().addEventListener('click', this.openNewTab.bind(this, false)); + this.urlbarInput().addEventListener('keydown', this.handleUrlbarInputKeydown.bind(this)); + this.navbarBackButton().addEventListener('click', this.handleNavbarBackButton.bind(this)); + this.navbarForwardButton().addEventListener('click', this.handleNavbarForwardButton.bind(this)); + this.navbarReloadButton().addEventListener('click', this.handleNavbarReloadButton.bind(this)); + this.navbarHomeButton().addEventListener('click', this.handleNavbarHomeButton.bind(this)); + }, + + openNewTab: function(isPrivate, url) { + var tab = document.createElement('li'); + this.tablist().appendChild(tab); + + var favicon = document.createElement('img'); + favicon.classList.add('favicon'); + tab.appendChild(favicon); + + var title = document.createElement('span'); + title.classList.add('title'); + tab.appendChild(title); + + var closeButton = document.createElement('button'); + closeButton.classList.add('close-button'); + closeButton.dataset.icon = 'close'; + tab.appendChild(closeButton); + + var webview = document.createElement('webview'); + webview.src = url || this.DEFAULT_URL; + webview.classList.add('browser'); + webview.nodeintegration = true; + webview.nodeintegrationinsubframes = true; + webview.disablewebsecurity = true; + webview.webpreferences = "contextIsolation=false"; + webview.useragent = navigator.userAgent; + webview.preload = `file://./preload.js`; + this.browserContainer().appendChild(webview); + + webview.addEventListener('context-menu', this.handleContextMenu.bind(this)); + webview.addEventListener('page-favicon-updated', this.handlePageFaviconUpdated.bind(this)); + webview.addEventListener('page-title-updated', this.handlePageTitleUpdated.bind(this)); + webview.addEventListener('did-start-navigation', this.handleDidStartNavigation.bind(this)); + webview.addEventListener('did-change-theme-color', this.handleThemeColorUpdated.bind(this)); + webview.addEventListener('', this.handleThemeColorUpdated.bind(this)); + + const ipcListener = EventListener.appWindow; + const pattern = /^http:\/\/.*\.localhost:8081\//; + const cssURL = `http://shared.localhost:${location.port}/style/webview.css`; + const jsURL = `http://shared.localhost:${location.port}/js/webview.js`; + + + ['did-start-loading', 'did-start-navigation', 'did-stop-loading', 'dom-ready'].forEach((eventType) => { + webview.addEventListener(eventType, () => { + const xhr = new XMLHttpRequest(); + xhr.open('GET', cssURL, true); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4 && xhr.status === 200) { + const cssContent = xhr.responseText; + webview.insertCSS(cssContent); + } else if (xhr.readyState === 4) { + console.error('Failed to fetch CSS:', xhr.status, xhr.statusText); + } + }; + xhr.send(); + + const xhr1 = new XMLHttpRequest(); + xhr1.open('GET', jsURL, true); + xhr1.onreadystatechange = function () { + if (xhr1.readyState === 4 && xhr1.status === 200) { + const jsContent = xhr1.responseText; + webview.executeJavaScript(jsContent); + } else if (xhr1.readyState === 4) { + console.error('Failed to fetch JS:', xhr1.status, xhr1.statusText); + } + }; + xhr1.send(); + + if (pattern.test(webview.getURL())) { + webview.nodeintegration = true; + webview.nodeintegrationinsubframes = true; + webview.disablewebsecurity = true; + webview.webpreferences = "contextIsolation=false"; + webview.addEventListener('ipc-message', ipcListener); + } else { + webview.nodeintegration = false; + webview.nodeintegrationinsubframes = false; + webview.disablewebsecurity = false; + webview.webpreferences = "contextIsolation=true"; + webview.removeEventListener('ipc-message', ipcListener); + } + }); + }); + + const focus = () => { + var tabs = this.chrome.querySelectorAll('.tablist li'); + tabs.forEach(function(tab) { + tab.classList.remove('active'); + }); + + var webviews = this.chrome.querySelectorAll('.browser-container webview'); + webviews.forEach(function(webview) { + webview.classList.remove('active'); + }); + + tab.classList.add('active'); + webview.classList.add('active'); + }; + + focus(); + tab.addEventListener('click', focus.bind(this)); + closeButton.addEventListener('click', () => { + tab.remove(); + webview.remove(); + }); + }, + + handleUrlbarInputKeydown: function(event) { + if (event.key === 'Enter') { + var activeTab = this.chrome.querySelector('.tablist li.active'); + var webview = this.chrome.querySelector('.browser-container .browser.active'); + var url = event.target.value; + webview.src = url; + } + }, + + handleNavbarBackButton: function() { + var webview = this.chrome.querySelector('.browser-container .browser.active'); + if (webview.canGoBack()) { + webview.goBack(); + } + }, + + handleNavbarForwardButton: function() { + var webview = this.chrome.querySelector('.browser-container .browser.active'); + if (webview.canGoForward()) { + webview.goForward(); + } + }, + + handleNavbarReloadButton: function() { + var webview = this.chrome.querySelector('.browser-container .browser.active'); + webview.reload(); + }, + + handleNavbarHomeButton: function() { + var webview = this.chrome.querySelector('.browser-container .browser.active'); + webview.src = this.DEFAULT_URL; + }, + + handleContextMenu: function(event) { + console.log(event); + contextMenu(event.params.x, event.params.y, [ + { + name: 'Copy', + disabled: !event.params.editFlags.canCopy, + onclick: () => { + webview.focus(); + webview.copy(); + }, + }, + { + name: 'Cut', + disabled: !event.params.editFlags.canCut, + onclick: () => { + webview.focus(); + webview.cut(); + }, + }, + { + name: 'Paste', + disabled: !event.params.editFlags.canPaste, + onclick: () => { + webview.focus(); + webview.paste(); + }, + }, + { + name: 'Select All', + disabled: !event.params.editFlags.canSelectAll, + onclick: () => { + webview.focus(); + webview.selectAll(); + }, + }, + { + name: 'Delete', + disabled: !event.params.editFlags.canDelete, + onclick: () => { + webview.focus(); + webview.delete(); + }, + }, + ]); + }, + + handlePageFaviconUpdated: function(event) { + var favicon = this.chrome.querySelector('.tablist .active .favicon'); + favicon.src = event.favicons[0]; + }, + + handlePageTitleUpdated: function(event) { + var title = this.chrome.querySelector('.tablist .active .title'); + title.textContent = event.title; + }, + + handleDidStartNavigation: function() { + var webview = this.chrome.querySelector('.browser-container .browser.active'); + this.urlbarInput().value = webview.getURL(); + var url = new URL(webview.getURL()); + this.urlbarDisplayUrl().innerHTML = ` +
    ${url.protocol}//
    +
    ${url.host}
    +
    ${url.pathname}
    +
    ${url.search}
    +
    ${url.hash}
    + `; + }, + + handleThemeColorUpdated: function(event) { + var webview = this.chrome.querySelector('.browser-container .browser.active'); + const color = event.themeColor; + webview.dataset.themeColor = color; + this.chrome.style.setProperty('--theme-color', color); + + // Calculate the luminance of the color + const luminance = this.calculateLuminance(color); + + // If the color is light (luminance > 0.5), add 'light' class to the status bar + if (luminance > 0.5) { + this.statusbar.classList.add('light'); + this.softwareButtons.classList.add('light'); + } else { + // Otherwise, remove 'light' class + this.statusbar.classList.remove('light'); + this.softwareButtons.classList.remove('light'); + } + }, + + calculateLuminance: function (color) { + // Convert the color to RGB values + const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color); + const r = parseInt(rgb[1], 16); + const g = parseInt(rgb[2], 16); + const b = parseInt(rgb[3], 16); + + // Calculate relative luminance + const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255; + + return luminance; + }, +}; diff --git a/js/event_listener.js b/js/event_listener.js new file mode 100644 index 0000000..e400cba --- /dev/null +++ b/js/event_listener.js @@ -0,0 +1,52 @@ +const EventListener = { + init: function () { + window.addEventListener('message', this.onMessage); + window.addEventListener('notification', this.onNotification); + }, + + onMessage: function (event) { + // Check the message type + if (event.data.type === 'focus') { + // Process the focus event message + const { elementNode, isFocused } = event.data; + + // Perform actions based on the focus event + if (isFocused) { + console.log(`Element with ID '${elementNode}' is focused`); + Keyboard.show(); + } else { + console.log(`Element with ID '${elementNode}' is blurred`); + Keyboard.hide(); + } + } + }, + + appWindow: function (event) { + switch (event.channel) { + case 'open-app': + EventListener.onAppOpen(event); + break; + + case 'notification': + EventListener.onNotification(event); + break; + + default: + break; + } + }, + + onAppOpen: function (event) { + const { data } = event.args[0]; + AppWindow.create(data.manifestUrl, { originPos: { x: data.xOrigin, y: data.yOrigin } }); + }, + + onNotification: function (event) { + if (event.data.channel === 'notification') { + const { data } = event.args[0]; + NotificationToaster.showNotification(data.title, data.config); + } + } +} + +EventListener.init(); diff --git a/js/keybinds.js b/js/keybinds.js new file mode 100644 index 0000000..a9f4bd8 --- /dev/null +++ b/js/keybinds.js @@ -0,0 +1,5 @@ +const Keybinds = { + init: function () {} +} + +Keybinds.init(); diff --git a/js/keyboard.js b/js/keyboard.js new file mode 100644 index 0000000..1c33b49 --- /dev/null +++ b/js/keyboard.js @@ -0,0 +1,228 @@ +const Keyboard = { + screen: document.getElementById("screen"), + keyboard: document.getElementById("keyboard"), + keyboardSuggestions: document.getElementById("keyboard-auto-correct"), + keyboardContent: document.getElementById("keyboard-content"), + keyboardLanguages: document.getElementById("keyboard-languages"), + keyboardLanguagesButton: document.getElementById("keyboard-languages-button"), + toggleButton: document.getElementById("software-keyboard-button"), + data: { + letters: '', + shift: '', + symbols: '', + }, + language: 'en-US', + inputText: '', + + keySound: new Audio('/resources/sounds/key.wav'), + keySpecialSound: new Audio('/resources/sounds/key_special.wav'), + + init: async function () { + await fetch(`/keyboard_layouts/${this.language}/letters.txt`) + .then(response => response.text()) + .then(function (data) { + Keyboard.data.letters = data; + }); + await fetch(`/keyboard_layouts/${this.language}/shift.txt`) + .then(response => response.text()) + .then(function (data) { + Keyboard.data.shift = data; + }); + await fetch(`/keyboard_layouts/${this.language}/symbols.txt`) + .then(response => response.text()) + .then(function (data) { + Keyboard.data.symbols = data; + }); + + this.useLayout(Keyboard.data.letters); + + // Event listeners for input focus and blur + this.toggleButton.addEventListener('click', this.toggle.bind(this)); + }, + + useLayout: function (data) { + this.keyboardContent.innerHTML = ''; + + var lines = data.split(process.platform == 'win32' ? '\r\n' : '\n'); + lines.forEach(line => { + if (!line) { + return; + } + + var row = document.createElement('div'); + row.classList.add('row'); + this.keyboardContent.appendChild(row); + + var keys = line.split(' '); + keys.forEach(key => { + if (!key) { + return; + } + + var button = document.createElement('button'); + button.classList.add('key'); + button.addEventListener('click', () => { + if (document.activeElement) { + if (document.activeElement.nodeName === 'INPUT' || document.activeElement.nodeName === 'TEXTAREA') { + document.activeElement.focus(); + } else { + var webview = AppWindow.focusedWindow.querySelector('.browser'); + webview.focus(); + } + } + }); + row.appendChild(button); + + var letter = document.createElement('span'); + letter.classList.add('letter'); + button.appendChild(letter); + + var popout = document.createElement('div'); + popout.classList.add('popout'); + button.appendChild(popout); + + if (key === '{backspace}') { + button.classList.add("backspace"); + button.dataset.icon = 'dialer-delete'; + button.addEventListener('click', () => { + this.keySpecialSound.play(); + this.backspace(); + }); + } else if (key === '{shift}') { + button.classList.add("shift"); + button.dataset.icon = 'collapse-chevron'; + button.addEventListener('click', () => { + this.keySound.play(); + this.useLayout(Keyboard.data.shift); + }); + } else if (key === '{unshift}') { + button.classList.add("shift"); + button.classList.add("active"); + button.dataset.icon = 'expand-chevron'; + button.addEventListener('click', () => { + this.keySound.play(); + this.useLayout(Keyboard.data.letters); + }); + } else if (/\{symbols\:(.*)\}/.test(key)) { + button.classList.add("symbols"); + var keyString = key.replace('{', '').replace('}', '').split(':')[1]; + letter.textContent = keyString; + button.addEventListener('click', () => { + this.keySpecialSound.play(); + this.useLayout(Keyboard.data.symbols); + }); + } else if (/\{letters\:(.*)\}/.test(key)) { + button.classList.add("letters"); + var keyString = key.replace('{', '').replace('}', '').split(':')[1]; + letter.textContent = keyString; + button.addEventListener('click', () => { + this.keySpecialSound.play(); + this.useLayout(Keyboard.data.letters); + }); + } else if (/\{space\:(.*)\}/.test(key)) { + button.classList.add("space"); + var keyString = key.replace('{', '').replace('}', '').split(':')[1]; + letter.textContent = keyString; + button.addEventListener('click', () => { + this.keySpecialSound.play(); + this.input(' '); + }); + } else if (/\{return\:(.*)\}/.test(key)) { + button.classList.add("return"); + var keyString = key.replace('{', '').replace('}', '').split(':')[1]; + letter.textContent = keyString; + button.addEventListener('click', () => { + this.keySpecialSound.play(); + this.hide(); + }); + } else { + button.classList.add("has-popout"); + letter.textContent = key; + popout.textContent = key; + button.addEventListener('click', () => { + this.keySound.play(); + this.input(key); + }); + } + }); + }); + }, + + input: function (char) { + this.inputText += char; + // this.suggestWords(); + if (document.activeElement) { + if (document.activeElement.nodeName === 'INPUT' || document.activeElement.nodeName === 'TEXTAREA') { + document.activeElement.value += char; + } else { + var webview = AppWindow.focusedWindow.querySelector('.browser'); + webview.insertText(char); + } + } + }, + + backspace: function () { + this.inputText = this.inputText.slice(0, -1); + // this.suggestWords(); + if (document.activeElement) { + if (document.activeElement.nodeName === 'INPUT' || document.activeElement.nodeName === 'TEXTAREA') { + document.activeElement.value = document.activeElement.value.slice(0, -1); + } else { + var webview = AppWindow.focusedWindow.querySelector('.browser'); + webview.executeJavaScript(` + if (document.activeElement) { + // Append the key to the value of the focused element + document.activeElement.value = document.activeElement.value.slice(0, -1); + } + `); + } + } + }, + + show: function () { + this.screen.classList.add('keyboard-visible'); + this.keyboard.classList.add('visible'); + }, + + hide: function () { + this.screen.classList.remove('keyboard-visible'); + this.keyboard.classList.remove('visible'); + }, + + toggle: function () { + this.screen.classList.toggle('keyboard-visible'); + this.keyboard.classList.toggle('visible'); + }, + + suggestWords: function () { + var words = this.inputText.slice(' '); + var lastWord = words[words.length - 1]; + + const inputElement = document.createElement('input'); + inputElement.setAttribute('type', 'text'); + inputElement.setAttribute('spellcheck', 'true'); + inputElement.value = lastWord; + document.body.appendChild(inputElement); + + // Trigger the browser's spellcheck + inputElement.focus(); + inputElement.select(); + + // Get the suggestions provided by the browser dictionary + const suggestions = document.queryCommandValue('suggestions') || []; + + // Remove the temporary input element + document.body.removeChild(inputElement); + + // Return the suggestions as similar words + this.suggestions = suggestions.slice(0, 3); + this.suggestions.forEach(suggestion => { + var option = document.createElement('div'); + option.classList.add('suggestion'); + option.innerText = suggestion; + this.keyboardContent.appendChild(option); + }); + } +} + +Keyboard.init(); diff --git a/js/lockscreen/clock.js b/js/lockscreen/clock.js new file mode 100644 index 0000000..f71ae2f --- /dev/null +++ b/js/lockscreen/clock.js @@ -0,0 +1,25 @@ +const LockscreenClock = { + clockElement: document.getElementById('lockscreen-clock'), + is12HourFormat: true, // Set this flag to true for 12-hour format, or false for 24-hour format + + init: function () { + this.clockElement.classList.remove('hidden'); + + this.update(); + }, + + update: function () { + var currentTime = new Date(); + + this.clockElement.innerText = currentTime.toLocaleTimeString(navigator.language, { + hour12: this.is12HourFormat, + hour: 'numeric', + minute: '2-digit' + }); + + clearTimeout(this.timer); + this.timer = setTimeout(this.update.bind(this), 1000); + } +}; + +LockscreenClock.init(); diff --git a/js/lockscreen/date.js b/js/lockscreen/date.js new file mode 100644 index 0000000..3e679e3 --- /dev/null +++ b/js/lockscreen/date.js @@ -0,0 +1,25 @@ +const LockscreenDate = { + dateElement: document.getElementById('lockscreen-date'), + is12HourFormat: true, // Set this flag to true for 12-hour format, or false for 24-hour format + + init: function () { + this.dateElement.classList.remove('hidden'); + + this.update(); + }, + + update: function () { + var currentTime = new Date(); + + this.dateElement.innerText = currentTime.toLocaleDateString(navigator.language, { + year: 'numeric', + month: 'long', + day: 'numeric' + }); + + clearTimeout(this.timer); + this.timer = setTimeout(this.update.bind(this), 1000); + } +}; + +LockscreenDate.init(); diff --git a/js/lockscreen/motion.js b/js/lockscreen/motion.js new file mode 100644 index 0000000..0ba76e1 --- /dev/null +++ b/js/lockscreen/motion.js @@ -0,0 +1,128 @@ +const LockscreenMotion = { + motionElement: document.getElementById('lockscreen'), + lockscreenIcon: document.getElementById('lockscreen-icon'), + startY: 0, + currentY: 0, + isDragging: false, + threshold: 0.75, // Adjust the threshold as desired (0.0 to 1.0) + + lockSound: new Audio('/resources/sounds/lock.wav'), + unlockSound: new Audio('/resources/sounds/unlock.opus'), + + init: function() { + document.addEventListener('keyup', this.onKeyPress.bind(this)); + + this.motionElement.addEventListener('dblclick', this.onDoubleTap.bind(this)); + this.motionElement.addEventListener('pointerdown', this.onPointerDown.bind(this)); + document.addEventListener('pointermove', this.onPointerMove.bind(this)); + document.addEventListener('pointerup', this.onPointerUp.bind(this)); + + this.showMotionElement(); + }, + + onKeyPress: function(event) { + switch (event.code) { + case 'End': + this.showMotionElement(); + this.resetMotionElement(); + this.isDragging = false; + break; + + default: + break; + } + }, + + onDoubleTap: function() { + this.motionElement.classList.toggle('low-power'); + }, + + onPointerDown: function(event) { + event.preventDefault(); + this.startY = event.clientY; + this.currentY = this.startY; + this.isDragging = true; + }, + + onPointerMove: function(event) { + event.preventDefault(); + + if (this.isDragging) { + this.currentY = event.clientY; + const offsetY = this.startY - this.currentY; + const maxHeight = this.motionElement.offsetHeight; + var progress = offsetY / maxHeight; + + progress = Math.max(0, Math.min(1, progress)); // Limit progress between 0 and 1 + + this.updateMotionProgress(progress); // Update motion element opacity + } + }, + + onPointerUp: function() { + const offsetY = this.startY - this.currentY; + const maxHeight = this.motionElement.offsetHeight; + const progress = 1 - offsetY / maxHeight; + + this.motionElement.classList.add('transitioning'); + clearTimeout(this.timer); + this.timer = setTimeout(() => { + this.motionElement.classList.remove('transitioning'); + }, 500); + + if (progress >= this.threshold) { + this.motionElement.style.setProperty('--motion-progress', 1); + this.lockscreenIcon.classList.add('fail-unlock'); + this.lockscreenIcon.onanimationend = () => { + this.lockscreenIcon.classList.remove('fail-unlock'); + }; + } else { + this.motionElement.style.setProperty('--motion-progress', 0); + this.hideMotionElement(); + } + + this.isDragging = false; + }, + + updateMotionProgress: function(progress) { + const motionProgress = 1 - progress; + this.motionElement.style.setProperty('--motion-progress', motionProgress); + + if (motionProgress <= this.threshold) { + } else { + this.showMotionElement(); + } + }, + + hideMotionElement: function() { + if (this.isDragging) { + this.unlockSound.play(); + } + + this.motionElement.classList.add('transitioning'); + this.motionElement.classList.remove('visible'); + TimeIcon.iconElement.classList.remove('hidden'); + + clearTimeout(this.timer); + this.timer = setTimeout(() => { + this.motionElement.classList.remove('transitioning'); + }, 500); + }, + + showMotionElement: function() { + this.motionElement.classList.add('visible'); + this.motionElement.classList.remove('transitioning'); + TimeIcon.iconElement.classList.add('hidden'); + }, + + resetMotionElement: function() { + this.motionElement.classList.add('transitioning'); + clearTimeout(this.timer); + this.timer = setTimeout(() => { + this.motionElement.classList.remove('transitioning'); + }, 500); + this.motionElement.style.setProperty('--motion-progress', 1); + } +}; + +LockscreenMotion.init(); diff --git a/js/network_icon.js b/js/network_icon.js new file mode 100644 index 0000000..6714fdd --- /dev/null +++ b/js/network_icon.js @@ -0,0 +1,48 @@ +const NetworkIcon = { + iconElement: document.getElementById("statusbar-network"), + + init: function () { + this.update(); + }, + + update: function () { + si.wifiNetworks((networks, error) => { + if (error) { + console.error(error); + + this.iconElement.classList.add("hidden"); + } else { + this.networks = networks; + + // Find the connected network + const connectedNetwork = networks.find( + (network) => network.state === "connected" + ) || networks[0]; + + if (connectedNetwork) { + // Retrieve the signal strength + const signalStrength = connectedNetwork.quality; + + // Convert signal strength to percentage + const signalStrengthPercentage = signalStrength; + + console.log( + "Signal Strength:", + signalStrengthPercentage.toFixed(2) + "%" + ); + + this.iconElement.classList.remove("hidden"); + + this.iconElement.dataset.icon = `wifi-${Math.round( + signalStrengthPercentage / 25 + )}`; + } + } + }); + + clearTimeout(this.timer); + this.timer = setTimeout(this.update, 1000); + }, +}; + +NetworkIcon.init(); diff --git a/js/notification_toaster.js b/js/notification_toaster.js new file mode 100644 index 0000000..e7b7748 --- /dev/null +++ b/js/notification_toaster.js @@ -0,0 +1,73 @@ +const NotificationToaster = { + notificationElement: document.getElementById('notification-toaster'), + titleElement: document.getElementById('notification-title'), + detailElement: document.getElementById('notification-detail'), + progressElement: document.getElementById('notification-progress'), + badgeElement: document.getElementById('notification-badge'), + sourceNameElement: document.getElementById('notification-source-name'), + iconElement: document.getElementById('notification-icon'), + mediaElement: document.getElementById('notification-media'), + actionsElement: document.getElementById('notification-actions'), + + showNotification: function (title, options) { + const { detail, progress, badgeSrc, sourceName, iconSrc, mediaSrcs, actionButtons } = options; + + this.titleElement.innerText = title; + this.detailElement.innerText = detail; + this.progressElement.style.width = progress + '%'; + + if (badgeSrc) { + this.badgeElement.src = badgeSrc; + this.badgeElement.style.display = 'block'; + } else { + this.badgeElement.style.display = 'none'; + } + + this.sourceNameElement.innerText = sourceName; + + if (iconSrc) { + this.iconElement.src = iconSrc; + this.iconElement.style.display = 'block'; + } else { + this.iconElement.style.display = 'none'; + } + + if (mediaSrcs && mediaSrcs.length > 0) { + this.mediaElement.innerHTML = ''; + mediaSrcs.forEach(function (src) { + const imgElement = document.createElement('img'); + imgElement.src = src; + this.mediaElement.appendChild(imgElement); + }, this); + this.mediaElement.style.display = 'block'; + } else { + this.mediaElement.style.display = 'none'; + } + + if (actionButtons && actionButtons.length > 0) { + this.actionsElement.innerHTML = ''; + actionButtons.forEach(function (button) { + const buttonElement = document.createElement('button'); + buttonElement.textContent = button.label; + buttonElement.addEventListener('click', button.onclick); + if (button.recommend) { + buttonElement.classList.add('recommend'); + } + this.actionsElement.appendChild(buttonElement); + }, this); + this.actionsElement.style.display = 'block'; + } else { + this.actionsElement.style.display = 'none'; + } + + this.notificationElement.classList.add('visible'); + clearTimeout(this.timeout); + this.timeout = setTimeout(() => { + this.notificationElement.classList.remove('visible'); + }, 3000); + }, + + hideNotification: function () { + this.notificationElement.classList.remove('visible'); + } +}; diff --git a/js/screen_capture.js b/js/screen_capture.js new file mode 100644 index 0000000..3a10c7c --- /dev/null +++ b/js/screen_capture.js @@ -0,0 +1,66 @@ +const { ipcRenderer } = require('electron'); + +const ScreenCapture = { + elementId: 'screen', + mediaRecorder: null, + recordedChunks: [], + isRecording: false, + + toggleButton: document.getElementById('quick-settings-screen-capture'), + + init: function () { + this.toggleButton.addEventListener('click', () => { + screenCapture.toggleCapture(); + }); + }, + + startCapture: function () { + const element = document.getElementById(this.elementId); + const stream = element.captureStream(); + + // Create a MediaRecorder instance + this.mediaRecorder = new MediaRecorder(stream); + + // Event handler for recording data + this.mediaRecorder.ondataavailable = (event) => { + if (event.data.size > 0) { + this.recordedChunks.push(event.data); + } + }; + + // Event handler for recording stop + this.mediaRecorder.onstop = () => { + const blob = new Blob(this.recordedChunks, { type: 'video/webm' }); + const blobUrl = URL.createObjectURL(blob); + + // Send captured video URL to the main process via IPC + ipcRenderer.send('captured-video', blobUrl); + + // Reset recordedChunks array + this.recordedChunks = []; + }; + + // Start recording + this.mediaRecorder.start(); + this.isRecording = true; + console.log('Capture started'); + }, + + stopCapture: function () { + if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') { + this.mediaRecorder.stop(); + this.isRecording = false; + console.log('Capture stopped'); + } + }, + + toggleCapture: function () { + if (this.isRecording) { + this.stopCapture(); + } else { + this.startCapture(); + } + } +}; + +ScreenCapture.init(); diff --git a/js/splashscreen.js b/js/splashscreen.js new file mode 100644 index 0000000..2e9a1bb --- /dev/null +++ b/js/splashscreen.js @@ -0,0 +1,18 @@ +const Splashscreen = { + splashElement: document.getElementById('splashscreen'), + videoElement: document.getElementById('splashscreen-video'), + + bootAnimationFile: '/resources/videos/splashscreen.mp4', + + init: function () { + this.videoElement.src = this.bootAnimationFile; + this.videoElement.play(); + document.addEventListener('DOMContentLoaded', this.onLoad.bind(this)); + }, + + onLoad: function () { + this.splashElement.classList.add('hidden'); + } +}; + +Splashscreen.init(); diff --git a/js/time_icon.js b/js/time_icon.js new file mode 100644 index 0000000..f4a8e2e --- /dev/null +++ b/js/time_icon.js @@ -0,0 +1,25 @@ +const TimeIcon = { + iconElement: document.getElementById('statusbar-time'), + is12HourFormat: true, // Set this flag to true for 12-hour format, or false for 24-hour format + + init: function () { + this.iconElement.classList.remove('hidden'); + + this.update(); + }, + + update: function () { + var currentTime = new Date(); + + this.iconElement.innerText = currentTime.toLocaleTimeString(navigator.language, { + hour12: this.is12HourFormat, + hour: 'numeric', + minute: '2-digit' + }); + + clearTimeout(this.timer); + this.timer = setTimeout(this.update.bind(this), 1000); + } +}; + +TimeIcon.init(); diff --git a/js/utility_tray_motion.js b/js/utility_tray_motion.js new file mode 100644 index 0000000..3a9b5be --- /dev/null +++ b/js/utility_tray_motion.js @@ -0,0 +1,96 @@ +const UtilityTrayMotion = { + statusbar: document.getElementById('statusbar'), + motionElement: document.getElementById('utility-tray-motion'), + startY: 0, + currentY: 0, + isDragging: false, + threshold: 0.75, // Adjust the threshold as desired (0.0 to 1.0) + + init: function() { + this.statusbar.addEventListener('pointerdown', this.onPointerDown.bind(this)); + document.addEventListener('pointermove', this.onPointerMove.bind(this)); + document.addEventListener('pointerup', this.onPointerUp.bind(this)); + document.addEventListener('pointerleave', this.onPointerUp.bind(this)); + + this.motionElement.addEventListener('pointerdown', this.onPointerDown.bind(this)); + document.addEventListener('pointermove', this.onPointerMove.bind(this)); + document.addEventListener('pointerup', this.onPointerUp.bind(this)); + document.addEventListener('pointerleave', this.onPointerUp.bind(this)); + }, + + onPointerDown: function(event) { + event.preventDefault(); + this.startY = event.clientY; + this.currentY = this.startY; + this.isDragging = true; + }, + + onPointerMove: function(event) { + event.preventDefault(); + + if (this.isDragging) { + this.currentY = event.clientY; + const offsetY = this.startY - this.currentY; + const maxHeight = this.motionElement.offsetHeight; + var progress = offsetY / maxHeight; + + progress = Math.max(0, Math.min(1, progress)); // Limit progress between 0 and 1 + + this.updateMotionProgress(progress); // Update motion element opacity + } + }, + + onPointerUp: function() { + const offsetY = this.startY - this.currentY; + const maxHeight = this.motionElement.offsetHeight; + const progress = 1 - offsetY / maxHeight; + + if (progress >= this.threshold) { + this.motionElement.style.setProperty('--motion-progress', 1); + } else { + this.motionElement.style.setProperty('--motion-progress', 0); + this.hideMotionElement(); + } + + this.isDragging = false; + }, + + onPointerCancel: function() { + this.resetMotionElement(); + this.isDragging = false; + }, + + updateMotionProgress: function(progress) { + const motionProgress = 1 - progress; + this.motionElement.style.setProperty('--motion-progress', motionProgress); + + if (motionProgress <= this.threshold) { + this.motionElement.classList.add('fade-out'); + this.motionElement.classList.remove('fade-in'); + } else { + this.showMotionElement(); + this.motionElement.classList.add('fade-in'); + this.motionElement.classList.remove('fade-out'); + } + }, + + hideMotionElement: function() { + this.motionElement.classList.remove('visible'); + }, + + showMotionElement: function() { + this.motionElement.classList.add('visible'); + }, + + resetMotionElement: function() { + const offsetY = this.startY - this.currentY; + const maxHeight = this.motionElement.offsetHeight; + const progress = 1 - offsetY / maxHeight; + + if (progress >= this.threshold) { + this.motionElement.style.setProperty('--motion-progress', 1); + } + } +}; + +UtilityTrayMotion.init(); diff --git a/keyboard_layouts/ar/letters.txt b/keyboard_layouts/ar/letters.txt new file mode 100644 index 0000000..6b009c0 --- /dev/null +++ b/keyboard_layouts/ar/letters.txt @@ -0,0 +1,4 @@ +ض ص ث ق ف غ ع ه خ ح ج د +ش س ي ب ل ا ت ن م ك ط ذ +ئ ء ؤ ر لا ى ة و ز ظ {backspace} +{symbols:١٢٣} {space:مسافة} {return:إدخال} diff --git a/keyboard_layouts/ar/shift.txt b/keyboard_layouts/ar/shift.txt new file mode 100644 index 0000000..e69de29 diff --git a/keyboard_layouts/ar/symbols.txt b/keyboard_layouts/ar/symbols.txt new file mode 100644 index 0000000..5d74123 --- /dev/null +++ b/keyboard_layouts/ar/symbols.txt @@ -0,0 +1,4 @@ +١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ٠ +! @ # $ % ^ & * ( ) +- + _ = [ ] { } {backspace} +{letters:أب} {space:مسافة} . , {return:إدخال} diff --git a/keyboard_layouts/en-US/letters.txt b/keyboard_layouts/en-US/letters.txt new file mode 100644 index 0000000..f0c1259 --- /dev/null +++ b/keyboard_layouts/en-US/letters.txt @@ -0,0 +1,4 @@ +q w e r t y u i o p +a s d f g h j k l +{shift} z x c v b n m {backspace} +{symbols:123} {space:space} {return:return} diff --git a/keyboard_layouts/en-US/shift.txt b/keyboard_layouts/en-US/shift.txt new file mode 100644 index 0000000..1837d84 --- /dev/null +++ b/keyboard_layouts/en-US/shift.txt @@ -0,0 +1,4 @@ +Q W E R T Y U I O P +A S D F G H J K L +{unshift} Z X C V B N M {backspace} +{symbols:123} {space:space} {return:return} diff --git a/keyboard_layouts/en-US/symbols.txt b/keyboard_layouts/en-US/symbols.txt new file mode 100644 index 0000000..7d8fe80 --- /dev/null +++ b/keyboard_layouts/en-US/symbols.txt @@ -0,0 +1,4 @@ +1 2 3 4 5 6 7 8 9 0 +! @ # $ % ^ & * ( ) +- + _ = [ ] { } {backspace} +{letters:Abc} {space:space} . , {return:return} diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..d060e1e --- /dev/null +++ b/manifest.json @@ -0,0 +1,5 @@ +{ + "name": "System", + "role": "system", + "launch_url": "/index.html" +} diff --git a/resources/sounds/key.wav b/resources/sounds/key.wav new file mode 100644 index 0000000..1b4f74f Binary files /dev/null and b/resources/sounds/key.wav differ diff --git a/resources/sounds/key_special.wav b/resources/sounds/key_special.wav new file mode 100644 index 0000000..188b11c Binary files /dev/null and b/resources/sounds/key_special.wav differ diff --git a/resources/sounds/unlock.opus b/resources/sounds/unlock.opus new file mode 100644 index 0000000..e194bbd Binary files /dev/null and b/resources/sounds/unlock.opus differ diff --git a/resources/videos/splashscreen.mp4 b/resources/videos/splashscreen.mp4 new file mode 100644 index 0000000..c1aa2a8 Binary files /dev/null and b/resources/videos/splashscreen.mp4 differ diff --git a/resources/wallpapers/default.png b/resources/wallpapers/default.png new file mode 100644 index 0000000..104daa3 Binary files /dev/null and b/resources/wallpapers/default.png differ diff --git a/shared/fonts/JaliArabic-Black.ttf b/shared/fonts/JaliArabic-Black.ttf new file mode 100644 index 0000000..367c387 Binary files /dev/null and b/shared/fonts/JaliArabic-Black.ttf differ diff --git a/shared/fonts/JaliArabic-Bold.ttf b/shared/fonts/JaliArabic-Bold.ttf new file mode 100644 index 0000000..66030a4 Binary files /dev/null and b/shared/fonts/JaliArabic-Bold.ttf differ diff --git a/shared/fonts/JaliArabic-ExtraBold.ttf b/shared/fonts/JaliArabic-ExtraBold.ttf new file mode 100644 index 0000000..6654b2c Binary files /dev/null and b/shared/fonts/JaliArabic-ExtraBold.ttf differ diff --git a/shared/fonts/JaliArabic-ExtraLight.ttf b/shared/fonts/JaliArabic-ExtraLight.ttf new file mode 100644 index 0000000..0474858 Binary files /dev/null and b/shared/fonts/JaliArabic-ExtraLight.ttf differ diff --git a/shared/fonts/JaliArabic-Light.ttf b/shared/fonts/JaliArabic-Light.ttf new file mode 100644 index 0000000..c992f78 Binary files /dev/null and b/shared/fonts/JaliArabic-Light.ttf differ diff --git a/shared/fonts/JaliArabic-Medium.ttf b/shared/fonts/JaliArabic-Medium.ttf new file mode 100644 index 0000000..4271278 Binary files /dev/null and b/shared/fonts/JaliArabic-Medium.ttf differ diff --git a/shared/fonts/JaliArabic-Regular.ttf b/shared/fonts/JaliArabic-Regular.ttf new file mode 100644 index 0000000..434ba89 Binary files /dev/null and b/shared/fonts/JaliArabic-Regular.ttf differ diff --git a/shared/fonts/JaliArabic-SemiBold.ttf b/shared/fonts/JaliArabic-SemiBold.ttf new file mode 100644 index 0000000..4629b0a Binary files /dev/null and b/shared/fonts/JaliArabic-SemiBold.ttf differ diff --git a/shared/js/buttons.js b/shared/js/buttons.js new file mode 100644 index 0000000..4054f8f --- /dev/null +++ b/shared/js/buttons.js @@ -0,0 +1,39 @@ +// Add click event listener to elements with .ripple-button class +const rippleButtons = document.querySelectorAll(".ripple-button"); +rippleButtons.forEach((button) => { + button.addEventListener("click", createRipple); +}); + +// Create ripple effect on click +function createRipple(event) { + const button = event.currentTarget; + + // Create ripple element + const ripple = document.createElement("span"); + ripple.classList.add("ripple"); + + // Calculate ripple size based on button dimensions + const buttonRect = button.getBoundingClientRect(); + const size = Math.max(buttonRect.width, buttonRect.height) * 2; + + // Position ripple element + const posX = event.clientX - buttonRect.left - size / 2; + const posY = event.clientY - buttonRect.top - size / 2; + ripple.style.cssText = ` + width: ${size}px; + height: ${size}px; + top: ${posY}px; + left: ${posX}px; + `; + + // Append ripple element to the button + button.appendChild(ripple); + + // Add animation class to enable the ripple effect + ripple.classList.add("animate"); + + // Remove the ripple element after the animation is complete + setTimeout(() => { + ripple.remove(); + }, 1000); +} diff --git a/shared/js/panels.js b/shared/js/panels.js new file mode 100644 index 0000000..19ef3b2 --- /dev/null +++ b/shared/js/panels.js @@ -0,0 +1,35 @@ +// Panel object +var Panel = { + panels: null, + + // Initialize the panel object + init() { + this.panels = document.querySelectorAll('.panel'); + this.bindScrollEvents(); + }, + + // Bind scroll events to each panel + bindScrollEvents() { + this.panels.forEach(panel => { + const content = panel.querySelector('.content'); + + content.addEventListener('scroll', () => { + const scrollPosition = content.scrollTop; + var progress = scrollPosition / 80; + if (progress >= 1) { + progress = 1; + } + + this.setProgress(panel, progress); + }); + }); + }, + + // Set progress value on the header bar + setProgress(panel, progress) { + panel.style.setProperty('--progress', progress); + } +}; + +// Initialize the Panel object +Panel.init(); diff --git a/shared/js/webview-preload.js b/shared/js/webview-preload.js new file mode 100644 index 0000000..5e73490 --- /dev/null +++ b/shared/js/webview-preload.js @@ -0,0 +1,26 @@ +const { ipcRenderer } = require('electron'); + +document.addEventListener('focus', event => { + if (event.target.nodeName === 'INPUT') { + window.parent.postMessage({ type: 'focus', element: event.target.id, isFocused: true }, '*'); + } +}, true); + +document.addEventListener('blur', event => { + if (event.target.nodeName === 'INPUT') { + window.parent.postMessage({ type: 'focus', element: event.target.id, isFocused: false }, '*'); + } +}, true); + +// Override the Notification constructor +window.Notification = class Notification { + constructor(title, options) { + // Forward the notification data to the parent renderer process + ipcRenderer.sendToHost('notification', { + data: { + title, + options + } + }); + } +}; diff --git a/shared/js/webview.js b/shared/js/webview.js new file mode 100644 index 0000000..e69de29 diff --git a/shared/manifest.json b/shared/manifest.json new file mode 100644 index 0000000..63f4964 --- /dev/null +++ b/shared/manifest.json @@ -0,0 +1,5 @@ +{ + "name": "Shared", + "role": "system", + "launch_url": "/index.html" +} diff --git a/shared/style/buttons.css b/shared/style/buttons.css new file mode 100644 index 0000000..e03126b --- /dev/null +++ b/shared/style/buttons.css @@ -0,0 +1,34 @@ +.ripple-button { + position: relative; + overflow: hidden; + display: inline-block; + cursor: pointer; +} + +.ripple { + content: ""; + display: block; + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + background: radial-gradient(circle at 50% 50%, rgba(0, 0, 0, 0.2), transparent 75%); + border-radius: 50%; + pointer-events: none; +} + +.ripple.animate { + animation: rippleEffect 0.75s ease forwards; +} + +@keyframes rippleEffect { + 0% { + opacity: 1; + transform: scale(0); + } + 100% { + opacity: 0; + transform: scale(1); + } +} diff --git a/shared/style/fonts.css b/shared/style/fonts.css new file mode 100644 index 0000000..5f61b22 --- /dev/null +++ b/shared/style/fonts.css @@ -0,0 +1,51 @@ +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-ExtraLight.ttf); + font-weight: 200; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Light.ttf); + font-weight: 300; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Regular.ttf); + font-weight: 400; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Medium.ttf); + font-weight: 500; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-SemiBold.ttf); + font-weight: 600; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Bold.ttf); + font-weight: 700; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-ExtraBold.ttf); + font-weight: 800; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Black.ttf); + font-weight: 900; +} + +*, ::placeholder { + font-family: 'Jali Arabic'; +} diff --git a/shared/style/headerbars.css b/shared/style/headerbars.css new file mode 100644 index 0000000..9c2710c --- /dev/null +++ b/shared/style/headerbars.css @@ -0,0 +1,79 @@ +.headerbar { + width: 100%; + height: calc(var(--statusbar-height) + 5rem + (4rem * (1 - var(--progress, 0)))); + background-color: rgba(var(--headerbar-r), var(--headerbar-g), var(--headerbar-b), calc(var(--progress, 0) * 0.75)); + display: flex; + padding: var(--statusbar-height) 1rem 0; + box-sizing: border-box; + z-index: 10; + flex-shrink: 0; + backdrop-filter: blur(20px) saturate(calc(100% + (80% * var(--progress, 0)))); +} + +.headerbar .safezone { + width: 100%; + max-width: 74.5rem; + margin: 0 auto; + display: flex; +} + +.headerbar h1 { + flex-grow: 1; + margin: 0; + padding: 0 1rem; + box-sizing: border-box; + height: calc(5rem - (1rem * (1 - var(--progress, 0)))); + line-height: calc(5rem - (1rem * (1 - var(--progress, 0)))); + display: inline-block; + color: var(--text-color); + font-weight: normal; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + transform: translateY(calc(4.5rem * (1 - var(--progress, 0)))); + width: 100%; + font-size: calc(2rem + (0.8rem * (1 - var(--progress, 0)))); +} + +.headerbar a + h1 { + transform: translate(calc(-4rem * (1 - var(--progress, 0))), calc(4.5rem * (1 - var(--progress, 0)))); +} + +.headerbar a { + width: 4rem; + height: 4rem; + text-decoration: none; + line-height: 4rem; + border-radius: 50%; + display: inline-block; + color: var(--text-color); + flex-shrink: 0; + margin: 0.5rem 0; + text-align: center; + padding: 0 1rem; + box-sizing: border-box; +} + +.headerbar a:hover { + background-color: var(--item-hover); +} + +.headerbar a:active { + background-color: var(--item-active); +} + +.headerbar a[data-icon]::before { + width: 2rem; + height: 4rem; + line-height: 4rem; + font-size: 2rem; +} + +.headerbar menu[role="toolbar"] { + display: inline-flex; + height: 5rem; + flex-shrink: 0; + margin: 0; + padding: 0; + /* transform: translate(0, calc(50% * (1 - var(--progress, 0)))); */ +} diff --git a/shared/style/icons/fonts/openorchid-icons.eot b/shared/style/icons/fonts/openorchid-icons.eot new file mode 100644 index 0000000..92675a1 Binary files /dev/null and b/shared/style/icons/fonts/openorchid-icons.eot differ diff --git a/shared/style/icons/fonts/openorchid-icons.svg b/shared/style/icons/fonts/openorchid-icons.svg new file mode 100644 index 0000000..5a9e7a0 --- /dev/null +++ b/shared/style/icons/fonts/openorchid-icons.svg @@ -0,0 +1,959 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/shared/style/icons/fonts/openorchid-icons.ttf b/shared/style/icons/fonts/openorchid-icons.ttf new file mode 100644 index 0000000..666be18 Binary files /dev/null and b/shared/style/icons/fonts/openorchid-icons.ttf differ diff --git a/shared/style/icons/fonts/openorchid-icons.woff b/shared/style/icons/fonts/openorchid-icons.woff new file mode 100644 index 0000000..c516071 Binary files /dev/null and b/shared/style/icons/fonts/openorchid-icons.woff differ diff --git a/shared/style/icons/icons.css b/shared/style/icons/icons.css new file mode 100644 index 0000000..a369788 --- /dev/null +++ b/shared/style/icons/icons.css @@ -0,0 +1,1454 @@ +/* Generated by grunt-webfont */ +/* Based on https://github.com/endtwist/fontcustom/blob/master/lib/fontcustom/templates/fontcustom.css */ + + +@font-face { + font-family: "openorchid-icons"; + src: url('fonts/openorchid-icons.eot'); + src: url('fonts/openorchid-icons.eot') format('embedded-opentype'), + url('fonts/openorchid-icons.ttf') format('truetype'), + url('fonts/openorchid-icons.woff') format('woff'), + url('fonts/openorchid-icons.svg#openorchid-icons') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + + +[data-icon]:before, +.ligature-icons { + font-family: "openorchid-icons"; + content: attr(data-icon); + display: inline-block; + font-weight: 500; + font-style: normal; + text-decoration: inherit; + text-transform: none; + text-rendering: optimizeLegibility; + font-size: 30px; + -webkit-font-smoothing: antialiased; +} + + +.icon-accessibility:before { + content: "\e900"; +} +.icon-achievement:before { + content: "\e901"; +} +.icon-activecall-bluetooth:before { + content: "\e902"; +} +.icon-activecall-hangup:before { + content: "\e903"; +} +.icon-activecall-hold:before { + content: "\e904"; +} +.icon-activecall-mergecalls:before { + content: "\e905"; +} +.icon-activecall-mute:before { + content: "\e906"; +} +.icon-activecall-pickup:before { + content: "\e907"; +} +.icon-activecall-sms:before { + content: "\e908"; +} +.icon-activecall-speaker:before { + content: "\e909"; +} +.icon-activecall-switchlines:before { + content: "\e90a"; +} +.icon-activecall-voicemail:before { + content: "\e90b"; +} +.icon-add:before { + content: "\e90c"; +} +.icon-addons:before { + content: "\e90d"; +} +.icon-airplane:before { + content: "\e90e"; +} +.icon-alarm-clock:before { + content: "\e90f"; +} +.icon-alarmstop:before { + content: "\e910"; +} +.icon-album:before { + content: "\e911"; +} +.icon-all-day:before { + content: "\e912"; +} +.icon-apps:before { + content: "\e913"; +} +.icon-artist:before { + content: "\e914"; +} +.icon-attachments:before { + content: "\e915"; +} +.icon-audio:before { + content: "\e916"; +} +.icon-auth:before { + content: "\e917"; +} +.icon-auto-enhance-spark:before { + content: "\e918"; +} +.icon-back:before { + content: "\e91a"; +} +.icon-back-light:before { + content: "\e91b"; +} +.icon-battery:before { + content: "\e91c"; +} +.icon-battery-0:before { + content: "\e91d"; +} +.icon-battery-10:before { + content: "\e91e"; +} +.icon-battery-100:before { + content: "\e927"; +} +.icon-battery-20:before { + content: "\e91f"; +} +.icon-battery-30:before { + content: "\e920"; +} +.icon-battery-40:before { + content: "\e921"; +} +.icon-battery-50:before { + content: "\e922"; +} +.icon-battery-60:before { + content: "\e923"; +} +.icon-battery-70:before { + content: "\e924"; +} +.icon-battery-80:before { + content: "\e925"; +} +.icon-battery-90:before { + content: "\e926"; +} +.icon-battery-charging:before { + content: "\e928"; +} +.icon-battery-charging-0:before { + content: "\e929"; +} +.icon-battery-charging-10:before { + content: "\e92a"; +} +.icon-battery-charging-100:before { + content: "\e933"; +} +.icon-battery-charging-20:before { + content: "\e92b"; +} +.icon-battery-charging-30:before { + content: "\e92c"; +} +.icon-battery-charging-40:before { + content: "\e92d"; +} +.icon-battery-charging-50:before { + content: "\e92e"; +} +.icon-battery-charging-60:before { + content: "\e92f"; +} +.icon-battery-charging-70:before { + content: "\e930"; +} +.icon-battery-charging-80:before { + content: "\e931"; +} +.icon-battery-charging-90:before { + content: "\e932"; +} +.icon-bell:before { + content: "\e934"; +} +.icon-bluetooth:before { + content: "\e935"; +} +.icon-bookmark:before { + content: "\e936"; +} +.icon-bookmarked:before { + content: "\e937"; +} +.icon-brightness:before { + content: "\e938"; +} +.icon-browser-back:before { + content: "\e939"; +} +.icon-browser-closecancel:before { + content: "\e93a"; +} +.icon-browser-crashedtab:before { + content: "\e93b"; +} +.icon-browser-forward:before { + content: "\e93c"; +} +.icon-browser-home:before { + content: "\e93d"; +} +.icon-browser-library:before { + content: "\e93e"; +} +.icon-browser-moretabs:before { + content: "\e93f"; +} +.icon-browser-nofavicon:before { + content: "\e940"; +} +.icon-browser-pictureinpicture:before { + content: "\e941"; +} +.icon-browser-readermode:before { + content: "\e942"; +} +.icon-browser-reload:before { + content: "\e943"; +} +.icon-browser-search:before { + content: "\e944"; +} +.icon-browser-secure:before { + content: "\e945"; +} +.icon-browser-secureunverified:before { + content: "\e946"; +} +.icon-browser-sidetabs:before { + content: "\e947"; +} +.icon-browser-tabpreviews:before { + content: "\e948"; +} +.icon-browsing:before { + content: "\e949"; +} +.icon-bug:before { + content: "\e94a"; +} +.icon-calendar-alarm:before { + content: "\e94b"; +} +.icon-calendar-allday:before { + content: "\e94c"; +} +.icon-calendar-bullet:before { + content: "\e94d"; +} +.icon-calendar-dot:before { + content: "\e94e"; +} +.icon-calendar-eventalarm:before { + content: "\e94f"; +} +.icon-calendar-today:before { + content: "\e950"; +} +.icon-call:before { + content: "\e951"; +} +.icon-call-incoming:before { + content: "\e952"; +} +.icon-call-outgoing:before { + content: "\e95c"; +} +.icon-call-ringing:before { + content: "\e95d"; +} +.icon-calllog-checkboxoff:before { + content: "\e953"; +} +.icon-calllog-checkboxon-box:before { + content: "\e954"; +} +.icon-calllog-checkboxon-checkmark:before { + content: "\e955"; +} +.icon-calllog-expand:before { + content: "\e956"; +} +.icon-calllog-incomingcall:before { + content: "\e957"; +} +.icon-calllog-incomingsms:before { + content: "\e958"; +} +.icon-calllog-missedcall:before { + content: "\e959"; +} +.icon-calllog-outgoingcall:before { + content: "\e95a"; +} +.icon-calllog-outgoingsms:before { + content: "\e95b"; +} +.icon-camera:before { + content: "\e95e"; +} +.icon-camera-cameraorientation:before { + content: "\e95f"; +} +.icon-camera-flashauto:before { + content: "\e960"; +} +.icon-camera-flashoff:before { + content: "\e961"; +} +.icon-camera-flashon:before { + content: "\e962"; +} +.icon-camera-videorecorder:before { + content: "\e963"; +} +.icon-change-wallpaper:before { + content: "\e964"; +} +.icon-checked:before { + content: "\e965"; +} +.icon-clear-all:before { + content: "\e966"; +} +.icon-clearcancel-circle:before { + content: "\e967"; +} +.icon-clearcancel-cross:before { + content: "\e968"; +} +.icon-close:before { + content: "\e969"; +} +.icon-closecancel:before { + content: "\e96a"; +} +.icon-collapse-chevron:before { + content: "\e96b"; +} +.icon-compose:before { + content: "\e96c"; +} +.icon-contact-add:before { + content: "\e96d"; +} +.icon-contact-addfavorite:before { + content: "\e96e"; +} +.icon-contact-addimage:before { + content: "\e96f"; +} +.icon-contact-checkmark:before { + content: "\e970"; +} +.icon-contact-delete-circle:before { + content: "\e971"; +} +.icon-contact-delete-minus:before { + content: "\e972"; +} +.icon-contact-detailfacebook-f:before { + content: "\e973"; +} +.icon-contact-detailfacebook-square:before { + content: "\e974"; +} +.icon-contact-email:before { + content: "\e975"; +} +.icon-contact-favorite:before { + content: "\e976"; +} +.icon-contact-favorited:before { + content: "\e977"; +} +.icon-contact-favoritedcontact:before { + content: "\e978"; +} +.icon-contact-find:before { + content: "\e979"; +} +.icon-contact-link:before { + content: "\e97a"; +} +.icon-contact-location:before { + content: "\e97b"; +} +.icon-contact-phone:before { + content: "\e97c"; +} +.icon-contact-sms:before { + content: "\e97e"; +} +.icon-contact-twitter:before { + content: "\e97f"; +} +.icon-contact-undo-roundarrow:before { + content: "\e981"; +} +.icon-contacts:before { + content: "\e97d"; +} +.icon-copy:before { + content: "\e982"; +} +.icon-costcontrol-topup:before { + content: "\e983"; +} +.icon-costcontrol-topuppay:before { + content: "\e984"; +} +.icon-costcontrol-topupwithcode:before { + content: "\e985"; +} +.icon-costcontrol-updatebalance:before { + content: "\e986"; +} +.icon-crop:before { + content: "\e987"; +} +.icon-cut:before { + content: "\e988"; +} +.icon-data:before { + content: "\e989"; +} +.icon-database:before { + content: "\e98a"; +} +.icon-delete:before { + content: "\e98b"; +} +.icon-desktop:before { + content: "\e98c"; +} +.icon-developer:before { + content: "\e98d"; +} +.icon-dialer-contacts:before { + content: "\e98e"; +} +.icon-dialer-delete:before { + content: "\e98f"; +} +.icon-dialer-dialpad:before { + content: "\e990"; +} +.icon-dialer-recentcalls:before { + content: "\e991"; +} +.icon-dialpad:before { + content: "\e992"; +} +.icon-discord:before { + content: "\e993"; +} +.icon-dislike:before { + content: "\e994"; +} +.icon-disliked:before { + content: "\e995"; +} +.icon-dismisskeyboard:before { + content: "\e996"; +} +.icon-display:before { + content: "\e997"; +} +.icon-do-not-track:before { + content: "\e998"; +} +.icon-download:before { + content: "\e999"; +} +.icon-download-circle:before { + content: "\e99a"; +} +.icon-edit:before { + content: "\e99b"; +} +.icon-edit-image:before { + content: "\e99d"; +} +.icon-editcontact:before { + content: "\e99c"; +} +.icon-eject:before { + content: "\e99e"; +} +.icon-email:before { + content: "\e99f"; +} +.icon-email-addrecipient-circle:before { + content: "\e9a0"; +} +.icon-email-addrecipient-plus:before { + content: "\e9a1"; +} +.icon-email-attachment:before { + content: "\e9a2"; +} +.icon-email-downloadattachment:before { + content: "\e9a3"; +} +.icon-email-flag:before { + content: "\e9a4"; +} +.icon-email-forward:before { + content: "\e9a5"; +} +.icon-email-markread:before { + content: "\e9a6"; +} +.icon-email-markunread:before { + content: "\e9a7"; +} +.icon-email-move:before { + content: "\e9a8"; +} +.icon-email-removeattachment-circle:before { + content: "\e9a9"; +} +.icon-email-removeattachment-cross:before { + content: "\e9aa"; +} +.icon-email-reply:before { + content: "\e9ab"; +} +.icon-email-replyall:before { + content: "\e9ac"; +} +.icon-email-send:before { + content: "\e9ad"; +} +.icon-emailsmscalilog-editlist:before { + content: "\e9ae"; +} +.icon-emojis:before { + content: "\e9af"; +} +.icon-eraser:before { + content: "\e9b0"; +} +.icon-expand:before { + content: "\e9b1"; +} +.icon-expand-chevron:before { + content: "\e9b2"; +} +.icon-export:before { + content: "\e9b3"; +} +.icon-face-recognition:before { + content: "\e9b5"; +} +.icon-face-recognition-fail:before { + content: "\e9b6"; +} +.icon-facebook:before { + content: "\e9b4"; +} +.icon-favorites:before { + content: "\e9b7"; +} +.icon-feedback:before { + content: "\e9b8"; +} +.icon-file:before { + content: "\e9b9"; +} +.icon-find:before { + content: "\e9ba"; +} +.icon-fingerprint:before { + content: "\e9bb"; +} +.icon-firefox:before { + content: "\e9bc"; +} +.icon-flag:before { + content: "\e9bd"; +} +.icon-flashlight:before { + content: "\e9be"; +} +.icon-fm-favouritedstation:before { + content: "\e9bf"; +} +.icon-fm-sound:before { + content: "\e9c0"; +} +.icon-folder:before { + content: "\e9c1"; +} +.icon-forbidden:before { + content: "\e9c2"; +} +.icon-forward:before { + content: "\e9c3"; +} +.icon-forward-light:before { + content: "\e9c4"; +} +.icon-ftu-importgmail:before { + content: "\e9c5"; +} +.icon-ftu-importoutlook:before { + content: "\e9c6"; +} +.icon-ftu-importsdcard:before { + content: "\e9c7"; +} +.icon-ftu-importsim:before { + content: "\e9c8"; +} +.icon-fullscreen:before { + content: "\e9c9"; +} +.icon-fullscreen-exit:before { + content: "\e9ca"; +} +.icon-gallery-autoenhancespark:before { + content: "\e9cb"; +} +.icon-gallery-crop:before { + content: "\e9cd"; +} +.icon-gallery-crop-photo:before { + content: "\e9d2"; +} +.icon-gallery-crop1x1-mark:before { + content: "\e9ce"; +} +.icon-gallery-crop2x3-mark:before { + content: "\e9cf"; +} +.icon-gallery-crop3x2-mark:before { + content: "\e9d0"; +} +.icon-gallery-cropfree-mark:before { + content: "\e9d1"; +} +.icon-gallery-exposure:before { + content: "\e9d3"; +} +.icon-gallery-filterscircleopacity100:before { + content: "\e9d6"; +} +.icon-gallery-filterscircleopacity35:before { + content: "\e9d4"; +} +.icon-gallery-filterscircleopacity50:before { + content: "\e9d5"; +} +.icon-gallery-rotate:before { + content: "\e9d7"; +} +.icon-game:before { + content: "\e9d8"; +} +.icon-gerneral-unlock:before { + content: "\e9d9"; +} +.icon-gesture:before { + content: "\e9da"; +} +.icon-gmail:before { + content: "\e9db"; +} +.icon-google:before { + content: "\e9dc"; +} +.icon-grid:before { + content: "\e9dd"; +} +.icon-heart:before { + content: "\e9de"; +} +.icon-help:before { + content: "\e9df"; +} +.icon-history:before { + content: "\e9e0"; +} +.icon-home:before { + content: "\e9e1"; +} +.icon-homescreen:before { + content: "\e9e2"; +} +.icon-homescreendelete-circle:before { + content: "\e9e3"; +} +.icon-homescreendelete-cross:before { + content: "\e9e4"; +} +.icon-info:before { + content: "\e9e5"; +} +.icon-instagram:before { + content: "\e9e6"; +} +.icon-iris-scanner:before { + content: "\e9e7"; +} +.icon-iris-scanner-fail:before { + content: "\e9e8"; +} +.icon-iris-scanner-success:before { + content: "\e9e9"; +} +.icon-keyboard:before { + content: "\e9ea"; +} +.icon-keyboard-circle:before { + content: "\e9eb"; +} +.icon-languages:before { + content: "\e9ec"; +} +.icon-left:before { + content: "\e9ed"; +} +.icon-left-light:before { + content: "\e9ee"; +} +.icon-library:before { + content: "\e9ef"; +} +.icon-like:before { + content: "\e9f0"; +} +.icon-liked:before { + content: "\e9f1"; +} +.icon-link:before { + content: "\e9f2"; +} +.icon-linkedin:before { + content: "\e9f3"; +} +.icon-location:before { + content: "\e9f4"; +} +.icon-lock:before { + content: "\e9f5"; +} +.icon-logout:before { + content: "\e9f6"; +} +.icon-media-camera:before { + content: "\e9f7"; +} +.icon-media-info:before { + content: "\e9f8"; +} +.icon-media-pause:before { + content: "\e9f9"; +} +.icon-media-play:before { + content: "\e9fa"; +} +.icon-media-playcircle:before { + content: "\e9fb"; +} +.icon-media-repeatinfinite:before { + content: "\e9fc"; +} +.icon-media-repeatonce:before { + content: "\e9fd"; +} +.icon-media-seekbackward:before { + content: "\e9fe"; +} +.icon-media-seekforward:before { + content: "\e9ff"; +} +.icon-media-shuffle:before { + content: "\ea00"; +} +.icon-media-skipbackward:before { + content: "\ea01"; +} +.icon-media-skipforward:before { + content: "\ea02"; +} +.icon-media-songs:before { + content: "\ea03"; +} +.icon-media-stop:before { + content: "\ea04"; +} +.icon-media-storage:before { + content: "\ea05"; +} +.icon-menu:before { + content: "\ea06"; +} +.icon-messages:before { + content: "\ea07"; +} +.icon-mic:before { + content: "\ea08"; +} +.icon-miscellaneous-editimage:before { + content: "\ea09"; +} +.icon-miscellaneous-select:before { + content: "\ea0a"; +} +.icon-miscellaneous-undo:before { + content: "\ea0b"; +} +.icon-moderator:before { + content: "\ea0c"; +} +.icon-moon:before { + content: "\ea0d"; +} +.icon-more:before { + content: "\ea0e"; +} +.icon-music-album:before { + content: "\ea0f"; +} +.icon-music-artist:before { + content: "\ea10"; +} +.icon-music-gridview:before { + content: "\ea11"; +} +.icon-music-playlist:before { + content: "\ea12"; +} +.icon-newadd:before { + content: "\ea13"; +} +.icon-nfc:before { + content: "\ea14"; +} +.icon-notification-bluetooth:before { + content: "\ea15"; +} +.icon-notification-bluetoothtransfer:before { + content: "\ea16"; +} +.icon-notification-cameramic:before { + content: "\ea17"; +} +.icon-notification-cameraon:before { + content: "\ea18"; +} +.icon-notification-circle:before { + content: "\ea19"; +} +.icon-notification-download:before { + content: "\ea1a"; +} +.icon-notification-downloadfailed-exclamation:before { + content: "\ea1b"; +} +.icon-notification-facebook:before { + content: "\ea1c"; +} +.icon-notification-importingfrommemorycard:before { + content: "\ea1d"; +} +.icon-notification-lowstorage:before { + content: "\ea1e"; +} +.icon-notification-mic:before { + content: "\ea1f"; +} +.icon-notifications:before { + content: "\ea20"; +} +.icon-options:before { + content: "\ea21"; +} +.icon-outlook:before { + content: "\ea22"; +} +.icon-paintbrush:before { + content: "\ea23"; +} +.icon-paintbucket:before { + content: "\ea24"; +} +.icon-paste:before { + content: "\ea25"; +} +.icon-pause:before { + content: "\ea26"; +} +.icon-permissions:before { + content: "\ea27"; +} +.icon-phone:before { + content: "\ea28"; +} +.icon-picture-in-picture:before { + content: "\ea29"; +} +.icon-pin:before { + content: "\ea2a"; +} +.icon-play:before { + content: "\ea2b"; +} +.icon-play-circle:before { + content: "\ea2c"; +} +.icon-playlist:before { + content: "\ea2d"; +} +.icon-power:before { + content: "\ea2e"; +} +.icon-qr:before { + content: "\ea2f"; +} +.icon-qr-scan:before { + content: "\ea30"; +} +.icon-quote:before { + content: "\ea31"; +} +.icon-reader-mode:before { + content: "\ea32"; +} +.icon-recent-calls:before { + content: "\ea33"; +} +.icon-redo:before { + content: "\ea34"; +} +.icon-reload:before { + content: "\ea35"; +} +.icon-repeat:before { + content: "\ea36"; +} +.icon-repeat-once:before { + content: "\ea37"; +} +.icon-right:before { + content: "\ea38"; +} +.icon-right-light:before { + content: "\ea39"; +} +.icon-save:before { + content: "\ea3a"; +} +.icon-sdcard:before { + content: "\ea3b"; +} +.icon-search:before { + content: "\ea3c"; +} +.icon-select:before { + content: "\ea3d"; +} +.icon-selectall:before { + content: "\ea3e"; +} +.icon-send:before { + content: "\ea3f"; +} +.icon-settings:before { + content: "\ea40"; +} +.icon-settings-aboutphone:before { + content: "\ea41"; +} +.icon-settings-accessibility:before { + content: "\ea42"; +} +.icon-settings-airplane:before { + content: "\ea43"; +} +.icon-settings-app-permissions:before { + content: "\ea44"; +} +.icon-settings-apps:before { + content: "\ea45"; +} +.icon-settings-appstorage:before { + content: "\ea46"; +} +.icon-settings-battery:before { + content: "\ea47"; +} +.icon-settings-bluetooth:before { + content: "\ea48"; +} +.icon-settings-brightness:before { + content: "\ea49"; +} +.icon-settings-brightness-lower:before { + content: "\ea4a"; +} +.icon-settings-call:before { + content: "\ea4b"; +} +.icon-settings-camera-permissions:before { + content: "\ea4c"; +} +.icon-settings-changewallpapericon:before { + content: "\ea4e"; +} +.icon-settings-contacts-permissions:before { + content: "\ea4f"; +} +.icon-settings-developer:before { + content: "\ea50"; +} +.icon-settings-deviceinfo:before { + content: "\ea51"; +} +.icon-settings-devicestorage-permissions:before { + content: "\ea52"; +} +.icon-settings-display:before { + content: "\ea53"; +} +.icon-settings-donottrack:before { + content: "\ea54"; +} +.icon-settings-download:before { + content: "\ea55"; +} +.icon-settings-email:before { + content: "\ea56"; +} +.icon-settings-facerecognition:before { + content: "\ea57"; +} +.icon-settings-feedback:before { + content: "\ea58"; +} +.icon-settings-findmydevice:before { + content: "\ea59"; +} +.icon-settings-fingerprint:before { + content: "\ea5a"; +} +.icon-settings-fmradio-permissions:before { + content: "\ea5b"; +} +.icon-settings-gesture:before { + content: "\ea5c"; +} +.icon-settings-gps:before { + content: "\ea5d"; +} +.icon-settings-gps-permissions:before { + content: "\ea5e"; +} +.icon-settings-help:before { + content: "\ea5f"; +} +.icon-settings-helpx:before { + content: "\ea60"; +} +.icon-settings-homescreen:before { + content: "\ea61"; +} +.icon-settings-irisscanner:before { + content: "\ea62"; +} +.icon-settings-languages:before { + content: "\ea63"; +} +.icon-settings-mediastorage:before { + content: "\ea64"; +} +.icon-settings-messages:before { + content: "\ea65"; +} +.icon-settings-network:before { + content: "\ea66"; +} +.icon-settings-nfc:before { + content: "\ea67"; +} +.icon-settings-notifications:before { + content: "\ea68"; +} +.icon-settings-persona:before { + content: "\ea69"; +} +.icon-settings-phonelock:before { + content: "\ea6a"; +} +.icon-settings-privacy:before { + content: "\ea6b"; +} +.icon-settings-simcardlock:before { + content: "\ea6c"; +} +.icon-settings-simtoolkit:before { + content: "\ea6d"; +} +.icon-settings-sound-max:before { + content: "\ea6e"; +} +.icon-settings-sound-min:before { + content: "\ea6f"; +} +.icon-settings-tethering:before { + content: "\ea70"; +} +.icon-settings-themes:before { + content: "\ea71"; +} +.icon-settings-time:before { + content: "\ea72"; +} +.icon-settings-usbstorage:before { + content: "\ea73"; +} +.icon-settings-wallpaper:before { + content: "\ea74"; +} +.icon-settings-wifi:before { + content: "\ea75"; +} +.icon-settings-wifi-1:before { + content: "\ea76"; +} +.icon-settings-wifi-2:before { + content: "\ea77"; +} +.icon-settings-wifi-3:before { + content: "\ea78"; +} +.icon-settings-wifi-4:before { + content: "\ea79"; +} +.icon-settings-wifi-lock:before { + content: "\ea7a"; +} +.icon-settings-wifi-lock-1:before { + content: "\ea7b"; +} +.icon-settings-wifi-lock-2:before { + content: "\ea7c"; +} +.icon-settings-wifi-lock-3:before { + content: "\ea7d"; +} +.icon-settings-wifi-lock-4:before { + content: "\ea7e"; +} +.icon-settings-wifi-permissions:before { + content: "\ea7f"; +} +.icon-share:before { + content: "\ea80"; +} +.icon-shopping-cart:before { + content: "\ea81"; +} +.icon-shuffle:before { + content: "\ea82"; +} +.icon-side-tabs:before { + content: "\ea83"; +} +.icon-signal-1:before { + content: "\ea84"; +} +.icon-signal-2:before { + content: "\ea85"; +} +.icon-signal-3:before { + content: "\ea86"; +} +.icon-signal-4:before { + content: "\ea87"; +} +.icon-signal-5:before { + content: "\ea88"; +} +.icon-sim:before { + content: "\ea89"; +} +.icon-skip-back:before { + content: "\ea8a"; +} +.icon-skip-forward:before { + content: "\ea8b"; +} +.icon-sms:before { + content: "\ea8c"; +} +.icon-snap-bottom:before { + content: "\ea8d"; +} +.icon-snap-bottom-left:before { + content: "\ea8e"; +} +.icon-snap-bottom-right:before { + content: "\ea8f"; +} +.icon-snap-left:before { + content: "\ea90"; +} +.icon-snap-right:before { + content: "\ea91"; +} +.icon-snap-top:before { + content: "\ea92"; +} +.icon-snap-top-left:before { + content: "\ea93"; +} +.icon-snap-top-right:before { + content: "\ea94"; +} +.icon-songs:before { + content: "\ea95"; +} +.icon-sound-max:before { + content: "\ea96"; +} +.icon-sound-min:before { + content: "\ea97"; +} +.icon-speaker:before { + content: "\ea98"; +} +.icon-splitscreen:before { + content: "\ea99"; +} +.icon-spotify-svgrepo-com:before { + content: "\ea9a"; +} +.icon-ssl:before { + content: "\ea9b"; +} +.icon-ssl-broken:before { + content: "\ea9c"; +} +.icon-stickers:before { + content: "\ea9d"; +} +.icon-storage:before { + content: "\ea9e"; +} +.icon-sync:before { + content: "\ea9f"; +} +.icon-tab-previews:before { + content: "\eaa1"; +} +.icon-tablet:before { + content: "\eaa0"; +} +.icon-taskswitcherappclose-circle:before { + content: "\eaa2"; +} +.icon-taskswitcherappclose-cross:before { + content: "\eaa3"; +} +.icon-television:before { + content: "\eaa4"; +} +.icon-tethering:before { + content: "\eaa5"; +} +.icon-textselection-copy:before { + content: "\eaa6"; +} +.icon-textselection-cut:before { + content: "\eaa7"; +} +.icon-textselection-paste:before { + content: "\eaa8"; +} +.icon-textselection-selectall:before { + content: "\eaa9"; +} +.icon-themes:before { + content: "\eaaa"; +} +.icon-threadnotsent-circle:before { + content: "\eaab"; +} +.icon-threadnotsent-exclamation:before { + content: "\eaac"; +} +.icon-tick:before { + content: "\eaad"; +} +.icon-tick-circle:before { + content: "\eaae"; +} +.icon-tiktok:before { + content: "\eaaf"; +} +.icon-time:before { + content: "\eab0"; +} +.icon-treadsent-check:before { + content: "\eab1"; +} +.icon-treadsent-circle:before { + content: "\eab2"; +} +.icon-tree:before { + content: "\eab3"; +} +.icon-tv:before { + content: "\eab4"; +} +.icon-twitch:before { + content: "\eab5"; +} +.icon-twitter:before { + content: "\eab6"; +} +.icon-undo:before { + content: "\eab7"; +} +.icon-upload:before { + content: "\eab8"; +} +.icon-usb:before { + content: "\eab9"; +} +.icon-user:before { + content: "\eaba"; +} +.icon-useraccoun-headers:before { + content: "\eabb"; +} +.icon-utility-airplanemode:before { + content: "\eabc"; +} +.icon-utility-arrow:before { + content: "\eabd"; +} +.icon-utility-battery:before { + content: "\eabe"; +} +.icon-utility-bluetooth:before { + content: "\eabf"; +} +.icon-utility-brightness:before { + content: "\eac0"; +} +.icon-utility-camera-lockedscreen:before { + content: "\eac1"; +} +.icon-utility-data:before { + content: "\eac2"; +} +.icon-utility-flashlight:before { + content: "\eac3"; +} +.icon-utility-maxvolume:before { + content: "\eac4"; +} +.icon-utility-mute-cease:before { + content: "\eac5"; +} +.icon-utility-mute-speaker:before { + content: "\eac6"; +} +.icon-utility-vibrate:before { + content: "\eac7"; +} +.icon-utility-volume:before { + content: "\eac8"; +} +.icon-utility-wifi:before { + content: "\eac9"; +} +.icon-vibrate:before { + content: "\eaca"; +} +.icon-video:before { + content: "\eacb"; +} +.icon-vpn:before { + content: "\eacc"; +} +.icon-wallpaper:before { + content: "\eacd"; +} +.icon-web:before { + content: "\eace"; +} +.icon-wifi:before { + content: "\eacf"; +} +.icon-wifi-1:before { + content: "\ead0"; +} +.icon-wifi-2:before { + content: "\ead1"; +} +.icon-wifi-3:before { + content: "\ead2"; +} +.icon-wifi-4:before { + content: "\ead3"; +} +.icon-windows:before { + content: "\ead4"; +} +.icon-wm-snapbottom:before { + content: "\ead5"; +} +.icon-wm-snapbottomleft:before { + content: "\ead6"; +} +.icon-wm-snapbottomright:before { + content: "\ead7"; +} +.icon-wm-snapleft:before { + content: "\ead8"; +} +.icon-wm-snapright:before { + content: "\ead9"; +} +.icon-wm-snaptop:before { + content: "\eada"; +} +.icon-wm-snaptopleft:before { + content: "\eadb"; +} +.icon-wm-snaptopright:before { + content: "\eadc"; +} +.icon-youtube:before { + content: "\eadd"; +} diff --git a/shared/style/lists.css b/shared/style/lists.css new file mode 100644 index 0000000..eb62410 --- /dev/null +++ b/shared/style/lists.css @@ -0,0 +1,122 @@ +.lists header { + width: 100%; + max-width: 74.8rem; + padding: 0 2rem; + box-sizing: border-box; + height: 3rem; + line-height: 3rem; + color: #858585; + font-size: 1.6rem; + font-weight: bold; + text-transform: uppercase; + margin: 1rem auto 0; +} + +.lists ul { + margin: 0 auto 1.5rem; + padding: 0.5rem; + background-color: var(--background-plus); + border-radius: 1.5rem; + width: calc(100% - 3rem); + max-width: 71.8rem; + box-sizing: border-box; +} + +.lists ul li { + position: relative; + margin: 0; + list-style: none; + min-height: 5rem; + display: inline-flex; + flex-direction: column; + justify-content: center; + width: 100%; + padding: 0 1.5rem; + box-sizing: border-box; + border-radius: 1rem; + color: var(--text-color); +} + +.lists ul li:hover { + background-color: var(--item-hover); +} + +.lists ul li:active { + background-color: var(--item-active); +} + +.lists ul li.selected { + background-color: var(--accent-color); + color: var(--accent-color-plus); +} + +.lists ul li[data-icon] { + padding-inline-start: 4.5rem; +} + +.lists ul li[data-icon]::before { + position: absolute; + top: 50%; + margin-top: -1.2rem; + left: 1.2rem; + color: var(--text-color); + width: 2.4rem; + height: 2.4rem; + line-height: 2.4rem; + font-size: 2.4rem; +} + +.lists ul li.selected[data-icon]::before { + color: var(--accent-color-plus); +} + +.lists ul li.page::after { + content: 'forward'; + font-family: "openorchid-icons"; + font-size: 2rem; + color: #858585; + text-align: end; + line-height: 5rem; +} + +.lists ul li.page.selected::after { + color: var(--accent-color-plus); + opacity: 0.5; +} + +.lists ul li::after { + content: ''; + position: absolute; + left: 1.5rem; + top: 0; + width: calc(100% - 3rem); + height: 100%; + pointer-events: none; + border-bottom: solid 0.1rem var(--item-hover); + box-sizing: border-box; +} + +.lists ul li:hover::after, +.lists ul li:active::after, +.lists ul li:last-child::after { + border-bottom: none; +} + +.lists ul li p { + margin: 0; + height: 2.2rem; + line-height: 2.2rem; + font-size: 1.6rem; + color: var(--text-color); +} + +.lists ul li.selected p { + color: var(--accent-color-plus); +} + +.lists ul li p:not(:first-child) { + height: 1.9rem; + line-height: 1.9rem; + font-size: 1.4rem; + opacity: 0.5; +} diff --git a/shared/style/main.css b/shared/style/main.css new file mode 100644 index 0000000..e2c8636 --- /dev/null +++ b/shared/style/main.css @@ -0,0 +1,15 @@ +html, body { + margin: 0; + padding: 0; + font-size: 10px; +} + +.app { + --statusbar-height: 4rem; + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: var(--background); +} diff --git a/shared/style/panels.css b/shared/style/panels.css new file mode 100644 index 0000000..b05a798 --- /dev/null +++ b/shared/style/panels.css @@ -0,0 +1,100 @@ +.panel { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: var(--background); + display: flex; + flex-direction: column; + overflow: hidden; + z-index: 50; +} + +.panel > .content { + width: 100%; + height: 100%; + flex-grow: 1; + overflow-y: auto; + margin-top: calc((-5rem - var(--statusbar-height)) * var(--progress, 0)); + scrollbar-width: none; +} + +.panel > .content aside { + margin: 0 auto 1.5rem; + padding: 0; + background-color: var(--background-minus); + border-radius: 1.5rem; + width: calc(100% - 3rem); + max-width: 71.8rem; + box-sizing: border-box; +} + +.panel > .content aside header { + width: 100%; + padding: 0 2rem; + box-sizing: border-box; + height: 3rem; + line-height: 3rem; + color: #858585; + font-size: 1.6rem; + font-weight: bold; + text-transform: uppercase; + margin: 1rem 0 0; +} + +.panel > .content aside ul { + margin: 0; + padding: 0 0.5rem 0.5rem; + width: 100%; + background-color: transparent; +} + +.panel > .content aside ul li { + min-height: 3.2rem; + background-color: transparent; +} + +.panel > .content aside ul li > a { + color: var(--accent-color); + width: max-content; + line-height: 2.2rem; + font-size: 1.6rem; + text-decoration: none; + transition: box-shadow 0.2s ease; +} + +.panel > .content aside ul li > a:hover { + box-shadow: 0 0.2rem 0 var(--accent-color); +} + +.panel > .content aside ul li > a:active { + opacity: 0.5; +} + +@media screen and (min-width: 983px) { + .panel > .headerbar .safezone { + margin-inline-start: 0; + } + + .panel > .content header, + .panel > .content ul { + margin-inline-start: 1.5rem; + } + + .panel > .content aside { + position: absolute; + right: 0; + top: calc(5rem + var(--statusbar-height) + (4rem * (1 - var(--progress, 0)))); + width: 22rem; + margin: calc(1.5rem * var(--progress, 0)) 1.5rem 1.5rem; + } +} + +@media screen and (min-width: 1536px) { + .panel > .headerbar .safezone, + .panel > .content header, + .panel > .content ul { + margin-inline-start: auto; + } +} diff --git a/shared/style/switches.css b/shared/style/switches.css new file mode 100644 index 0000000..be56c72 --- /dev/null +++ b/shared/style/switches.css @@ -0,0 +1,83 @@ +.pack-switch { + width: 100%; + display: inline-flex; +} + +.pack-switch > label { + width: 100%; + display: inline-flex; + flex-direction: column; + justify-content: center; + flex-grow: 1; +} + +.pack-switch > span { + flex-shrink: 0; + display: inline-flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.pack-switch > span input[type="checkbox"] { + background-color: var(--switch-normal); + width: 5rem; + height: 2.5rem; + border-radius: 2.5rem; + border: none; + position: relative; + outline: none; + appearance: none; + transition: all 0.1s ease; +} + +.pack-switch > span input[type="checkbox"]:hover { + background-color: var(--switch-hover); +} + +.pack-switch > span input[type="checkbox"]:hover { + background-color: var(--switch-active); +} + +.pack-switch > span input[type="checkbox"]:checked { + background-color: var(--accent-color); +} + +.pack-switch > span input[type="checkbox"]::before { + content: ''; + position: absolute; + left: 0.5rem; + top: 0.5rem; + width: 1.5rem; + height: 1.5rem; + background-color: var(--text-color); + border-radius: 1.5rem; + transition: all 0.3s cubic-bezier(0.2, 0, 0, 1); + z-index: 1; + pointer-events: none; +} + +.pack-switch > span input[type="checkbox"]:hover::before { + transform: scale(1.2); +} + +.pack-switch > span input[type="checkbox"]:active::before { + transform: scale(0.8); + width: 4rem; +} + +.pack-switch > span input[type="checkbox"]:checked::before { + left: 3rem; + transform: scale(1); + background-color: var(--accent-color-plus); +} + +.pack-switch > span input[type="checkbox"]:checked:hover::before { + transform: scale(1.2); +} + +.pack-switch > span input[type="checkbox"]:checked:active::before { + left: 0.5rem; + transform: scale(0.8); + width: 4rem; +} \ No newline at end of file diff --git a/shared/style/tablists.css b/shared/style/tablists.css new file mode 100644 index 0000000..e69de29 diff --git a/shared/style/theme.css b/shared/style/theme.css new file mode 100644 index 0000000..3690514 --- /dev/null +++ b/shared/style/theme.css @@ -0,0 +1,61 @@ +:root { + --accent-color: #0061e0; + --accent-color-plus: rgba(255, 255, 255, 0.75); + --accent-color-hover: rgba(255, 255, 255, 0.05); + --accent-color-active: rgba(255, 255, 255, 0.1); + + --background: #f0f6ff; + --background-plus: #fff; + --background-minus: #e0edff; + + --acrylic-background: rgba(224, 237, 255, 0.5); + --acrylic-background-plus: rgba(255, 255, 255, 0.75); + + --text-color: #333; + + --item-plus: rgba(0, 0, 0, 0.05); + --item-hover: rgba(0, 0, 0, 0.05); + --item-hover-plus: rgba(0, 0, 0, 0.1); + --item-active: rgba(0, 0, 0, 0.1); + --item-active-plus: rgba(0, 0, 0, 0.15); + + --headerbar-r: 224; + --headerbar-g: 237; + --headerbar-b: 255; + + --switch-normal: #d0e3ff; + --switch-hover: #c0d9ff; + --switch-active: #b0d0ff; +} + +@media screen and (prefers-color-scheme: dark) { + :root { + --accent-color: #80c2ff; + --accent-color-plus: rgba(0, 0, 0, 0.75); + --accent-color-hover: rgba(0, 0, 0, 0.05); + --accent-color-active: rgba(0, 0, 0, 0.1); + + --background: #000; + --background-plus: #212326; + --background-minus: #101215; + + --acrylic-background: rgba(16, 18, 21, 0.5); + --acrylic-background-plus: rgba(33, 35, 38, 0.75); + + --text-color: #e7e7e7; + + --item-plus: rgba(255, 255, 255, 0.05); + --item-hover: rgba(255, 255, 255, 0.05); + --item-hover-plus: rgba(255, 255, 255, 0.1); + --item-active: rgba(255, 255, 255, 0.1); + --item-active-plus: rgba(255, 255, 255, 0.15); + + --headerbar-r: 16; + --headerbar-g: 18; + --headerbar-b: 21; + + --switch-normal: #101215; + --switch-hover: #303235; + --switch-active: #404245; + } +} diff --git a/shared/style/webview.css b/shared/style/webview.css new file mode 100644 index 0000000..b81fc92 --- /dev/null +++ b/shared/style/webview.css @@ -0,0 +1,17 @@ +*, ::placeholder { + font-family: system-ui; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-thumb { + background-color: #858585; + background-clip: content-box; + border: 2px solid transparent; + border-radius: 8px; + width: 8px; + height: 8px; +} diff --git a/style/brightness.css b/style/brightness.css new file mode 100644 index 0000000..7284531 --- /dev/null +++ b/style/brightness.css @@ -0,0 +1,57 @@ +#brightness { + width: 100%; + background-color: var(--background-plus); + border-radius: 2rem; + height: 5rem; + display: flex; + padding: 0 1.5rem; + box-sizing: border-box; +} + +#brightness > span { + height: 5rem; + line-height: 5rem; + color: var(--text-color); +} + +#brightness > span[data-icon]::before { + font-size: 2.4rem; +} + +#brightness-slider { + width: 100%; + height: 2.4rem; + background-color: rgba(0, 0, 0, 0.125); + border-radius: 2rem; + margin: 1.3rem 1rem; + position: relative; +} + +#brightness-slider::before { + content: ''; + position: absolute; + width: calc(100% * var(--progress, 0.5)); + height: 2.4rem; + background-color: var(--accent-color); + border-radius: 2rem; +} + +#brightness-slider > .thumb { + content: ''; + position: absolute; + width: 1.6rem; + height: 1.6rem; + background-color: var(--accent-color-plus); + border-radius: 2rem; + left: calc((100% - 4rem) * var(--progress, 0.5)); + top: 0.4rem; + transition: all 0.3s cubic-bezier(0.2, 0, 0, 1); +} + +#brightness-slider:hover > .thumb { + transform: scale(1.2); +} + +#brightness-slider:active > .thumb { + transform: scale(0.8); +} diff --git a/style/cards_view.css b/style/cards_view.css new file mode 100644 index 0000000..8b7dccd --- /dev/null +++ b/style/cards_view.css @@ -0,0 +1,3 @@ +#cards-view { + visibility: hidden; +} diff --git a/style/chrome.css b/style/chrome.css new file mode 100644 index 0000000..77fec11 --- /dev/null +++ b/style/chrome.css @@ -0,0 +1,249 @@ +.chrome { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: hidden; +} + +.chrome .toolbar { + display: flex; + flex-direction: column; + position: absolute; + left: 0; + top: 0; + width: 100%; + padding: var(--statusbar-height, var(--chrome-toolbar-gap)) 0 var(--chrome-toolbar-gap); + box-sizing: border-box; + background-color: var(--theme-color, var(--background)); + transform: translateX(-100%); + visibility: hidden; + gap: var(--chrome-toolbar-gap); + overflow: hidden; + z-index: 10; + transition: all 0.5s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +.chrome.visible .toolbar { + transform: translateY(0); + visibility: visible; +} + +.chrome .tablist-holder { + width: 100%; + height: 4rem; + background-color: var(--theme-color, var(--background)); + flex-shrink: 0; + display: flex; + padding: 0 0.5rem; + box-sizing: border-box; + gap: var(--chrome-toolbar-gap); +} + +.chrome.hidden .tablist-holder { + display: none; +} + +.chrome .tablist { + height: 4rem; + display: flex; + gap: var(--chrome-toolbar-gap); + margin: 0; + padding: 0; +} + +.chrome .tablist li { + width: 24rem; + height: 4rem; + display: flex; + gap: var(--chrome-toolbar-gap); + list-style: none; + border-radius: 2rem; + margin: 0; + padding: 0 1rem; + padding-inline-end: 0.5rem; + box-sizing: border-box; + align-items: center; +} + +.chrome .tablist li.active { + background-color: var(--item-hover); +} + +.chrome .tablist li > .favicon { + width: 2rem; + height: 2rem; + flex-shrink: 0; +} + +.chrome .tablist li > .title { + width: 100%; + flex-grow: 1; + height: 2rem; + line-height: 2rem; + font-size: 1.4rem; + color: var(--text-color); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.chrome .tablist li > .close-button { + width: 3.2rem; + height: 3.2rem; + line-height: 3.2rem; + border: none; + background-color: transparent; + margin: 0; + padding: 0; + text-align: center; + color: var(--text-color); + border-radius: 50%; + flex-shrink: 0; +} + +.chrome .tablist li > .close-button:hover { + background-color: var(--item-hover); +} + +.chrome .tablist li > .close-button:active { + background-color: var(--item-active); +} + +.chrome .tablist li > .close-button[data-icon]::before { + font-size: 1.6rem; +} + +.chrome .navbar { + width: 100%; + height: 4rem; + background-color: var(--theme-color, var(--background)); + flex-shrink: 0; + display: flex; + padding: 0 0.5rem; + box-sizing: border-box; + gap: var(--chrome-toolbar-gap); +} + +.chrome .tablist-holder > button, +.chrome .navbar button { + min-width: 4rem; + height: 4rem; + line-height: 4rem; + margin: 0; + padding: 0 1rem; + box-sizing: border-box; + border: none; + border-radius: 50%; + flex-shrink: 0; + background-color: transparent; + color: var(--text-color); + font-size: 1.6rem; + text-align: center; +} + +.chrome .tablist-holder > button[data-icon]::before, +.chrome .navbar button[data-icon]::before { + font-size: 2rem; +} + +.chrome .tablist-holder > button:hover, +.chrome .navbar button:hover { + background-color: var(--item-hover); +} + +.chrome .tablist-holder > button:active, +.chrome .navbar button:active { + background-color: var(--item-active); +} + +/* .chrome .tablist-holder > button { + background-color: var(--item-hover); +} + +.chrome .tablist-holder > button:hover { + background-color: var(--item-hover-plus); +} + +.chrome .tablist-holder > button:active { + background-color: var(--item-active-plus); +} */ + +.chrome .navbar .urlbar { + width: 100%; + height: 4rem; + display: flex; + border-radius: 2rem; + margin: 0; + padding: 0; + background-color: var(--item-hover); + flex-grow: 1; + overflow: hidden; +} + +.chrome .navbar .urlbar > .urlbar-input { + width: 100%; + height: 4rem; + line-height: 4rem; + margin: 0; + padding: 0; + border: none; + background-color: transparent; + color: var(--text-color); + font-size: 1.6rem; + flex-grow: 1; + outline: none; + display: none; +} + +.chrome .navbar .urlbar > .urlbar-display-url { + width: 100%; + height: 4rem; + line-height: 4rem; + color: var(--text-color); + font-size: 1.6rem; + flex-grow: 1; + display: flex; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.chrome .navbar .urlbar:hover > .urlbar-input, +.chrome .navbar .urlbar:focus-within > .urlbar-input { + display: block; +} + +.chrome .navbar .urlbar:hover > .urlbar-display-url, +.chrome .navbar .urlbar:focus-within > .urlbar-display-url { + display: none; +} + +.chrome .navbar .urlbar > .urlbar-display-url .ignored { + opacity: 0.5; +} + +.chrome .browser-container { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + flex-grow: 1; +} + +.chrome .browser-container > .browser { + position: absolute; + width: 100%; + height: 100%; + visibility: hidden; +} + +.chrome .browser-container > .browser.active { + visibility: visible; +} + +#screen.context-menu-visible .chrome .browser-container > .browser { + pointer-events: none; +} diff --git a/style/icons/battery-0.svg b/style/icons/battery-0.svg new file mode 100644 index 0000000..58a5f37 --- /dev/null +++ b/style/icons/battery-0.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-10.svg b/style/icons/battery-10.svg new file mode 100644 index 0000000..58a5f37 --- /dev/null +++ b/style/icons/battery-10.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-100.svg b/style/icons/battery-100.svg new file mode 100644 index 0000000..45628bd --- /dev/null +++ b/style/icons/battery-100.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-20.svg b/style/icons/battery-20.svg new file mode 100644 index 0000000..58a5f37 --- /dev/null +++ b/style/icons/battery-20.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-30.svg b/style/icons/battery-30.svg new file mode 100644 index 0000000..58a5f37 --- /dev/null +++ b/style/icons/battery-30.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-40.svg b/style/icons/battery-40.svg new file mode 100644 index 0000000..58a5f37 --- /dev/null +++ b/style/icons/battery-40.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-50.svg b/style/icons/battery-50.svg new file mode 100644 index 0000000..58a5f37 --- /dev/null +++ b/style/icons/battery-50.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-60.svg b/style/icons/battery-60.svg new file mode 100644 index 0000000..58a5f37 --- /dev/null +++ b/style/icons/battery-60.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-70.svg b/style/icons/battery-70.svg new file mode 100644 index 0000000..58a5f37 --- /dev/null +++ b/style/icons/battery-70.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-80.svg b/style/icons/battery-80.svg new file mode 100644 index 0000000..029d33c --- /dev/null +++ b/style/icons/battery-80.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/icons/battery-90.svg b/style/icons/battery-90.svg new file mode 100644 index 0000000..0f7142a --- /dev/null +++ b/style/icons/battery-90.svg @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/style/images/back.png b/style/images/back.png new file mode 100644 index 0000000..f30b7cb Binary files /dev/null and b/style/images/back.png differ diff --git a/style/images/back.svg b/style/images/back.svg new file mode 100644 index 0000000..5f68225 --- /dev/null +++ b/style/images/back.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/style/images/home.png b/style/images/home.png new file mode 100644 index 0000000..a8fffc0 Binary files /dev/null and b/style/images/home.png differ diff --git a/style/images/home.svg b/style/images/home.svg new file mode 100644 index 0000000..da2654f --- /dev/null +++ b/style/images/home.svg @@ -0,0 +1,3 @@ + + + diff --git a/style/images/recents.png b/style/images/recents.png new file mode 100644 index 0000000..9458bc4 Binary files /dev/null and b/style/images/recents.png differ diff --git a/style/images/recents.svg b/style/images/recents.svg new file mode 100644 index 0000000..81f24a9 --- /dev/null +++ b/style/images/recents.svg @@ -0,0 +1,3 @@ + + + diff --git a/style/images/splitscreen.png b/style/images/splitscreen.png new file mode 100644 index 0000000..3182c49 Binary files /dev/null and b/style/images/splitscreen.png differ diff --git a/style/images/splitscreen.svg b/style/images/splitscreen.svg new file mode 100644 index 0000000..e67a8d5 --- /dev/null +++ b/style/images/splitscreen.svg @@ -0,0 +1,4 @@ + + + + diff --git a/style/keyboard.css b/style/keyboard.css new file mode 100644 index 0000000..97f3f68 --- /dev/null +++ b/style/keyboard.css @@ -0,0 +1,210 @@ +#keyboard { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 40%; + background-color: var(--background); + padding: 0.5rem; + box-sizing: border-box; + display: flex; + flex-direction: column; + z-index: 2048; + transform: translateY(100%); + transition: all 0.5s cubic-bezier(0.8, 0.1, 0.9, 0); +} + +#screen.software-buttons-enabled #keyboard { + height: calc(40% + var(--software-buttons-height)); + padding-bottom: var(--software-buttons-height); +} + +#keyboard.visible { + transform: translateY(0); + transition: all 0.5s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#keyboard-content { + display: flex; + flex-direction: column; + gap: 0.5rem; + flex-grow: 1; + margin: 0 auto; + width: 100%; + max-width: 76.8rem; +} + +#keyboard-content .row { + display: flex; + gap: 0.5rem; + flex-grow: 1; +} + +#keyboard-content .row .key { + background-color: var(--background-plus); + border: none; + border-radius: 1rem; + color: var(--text-color); + font-size: 1.6rem; + margin: 0; + padding: 0; + min-height: 3rem; + line-height: 100%; + flex-grow: 1; + width: 100%; + position: relative; +} + +#keyboard-content .row .key:not(.has-popout):active { + opacity: 0.75; +} + +#keyboard-content .row .key .popout { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: calc(100% + 4rem); + min-height: 3rem; + line-height: 4rem; + background-color: var(--accent-color); + border-radius: 1rem; + color: var(--accent-color-plus); + font-size: 1.6rem; + transition: all 0.2s cubic-bezier(0.2, 0.9, 0.1, 1); + visibility: visible; + transform: scaleY(0.75); + transform-origin: bottom; + opacity: 0; + pointer-events: none; +} + +#keyboard-content .row .key.has-popout:active .popout { + visibility: visible; + transform: scaleY(1); + opacity: 1; +} + +#keyboard-content .row .key.backspace, +#keyboard-content .row .key.symbols, +#keyboard-content .row .key.letters { + background-color: var(--background); + border-radius: 9999px; +} + +#keyboard-content .row .key.return { + background-color: var(--accent-color); + color: var(--accent-color-plus); + border-radius: 9999px; +} + +#keyboard-content .row .key.space { + width: 175%; + border-radius: 9999px; +} + +#keyboard-content .row .key.shift, +#keyboard-content .row .key.backspace { + width: 150%; +} + +#keyboard-content .row .key.shift[data-icon]::before, +#keyboard-content .row .key.backspace[data-icon]::before { + font-size: 2rem; +} + +#keyboard-toolbar { + flex-shrink: 0; + height: 4rem; + width: 100%; + display: flex; + margin: 0 auto; + margin-top: 1rem; + width: 100%; + max-width: 76.8rem; +} + +#keyboard-toolbar button { + color: var(--text-color); + background-color: transparent; + border: none; + width: 4rem; + height: 4rem; + border-radius: 50%; + flex-shrink: 0; +} + +#keyboard-toolbar button[data-icon]::before { + font-size: 2rem; +} + +#keyboard-toolbar .spacer { + height: 4rem; + width: 100%; + flex-grow: 1; +} + +#keyboard-auto-correct { + display: flex; + height: 3.6rem; + margin: 0 auto; + margin-bottom: 0.5rem; + width: 100%; + max-width: 76.8rem; +} + +#keyboard-auto-correct > .suggestion { + flex-grow: 1; + height: 3.6rem; + line-height: 3.6rem; + width: 100%; + color: var(--text-color); + opacity: 0.5; + text-align: center; + font-size: 1.4rem; + border-radius: 2rem; +} + +#keyboard-auto-correct > .suggestion:nth-child(2) { + opacity: 1; + background-color: var(--background-plus); +} + +/* Languages Dropdown */ +#keyboard-languages { + position: absolute; + left: 1rem; + bottom: 4rem; + width: 15rem; + height: 100%; + background: var(--background-plus); + border-radius: 1.5rem; + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.3); + overflow-y: auto; + padding: 0.5rem; + box-sizing: border-box; + visibility: hidden; + opacity: 0; + transform: translateY(-1rem); +} + +#screen.software-buttons-enabled #keyboard-languages { + bottom: calc(var(--software-buttons-height) + 4rem); +} + +#keyboard-languages .language { + padding: 0 1rem; + box-sizing: border-box; + width: 100%; + height: 4rem; + line-height: 4rem; + color: var(--text-color); + font-size: 1.6rem; + display: flex; + align-items: center; +} + +#keyboard-languages .language[data-icon]::before { + font-size: 2rem; + margin-inline-end: 1rem; +} diff --git a/style/lockscreen.css b/style/lockscreen.css new file mode 100644 index 0000000..fa8492d --- /dev/null +++ b/style/lockscreen.css @@ -0,0 +1,145 @@ +#lockscreen { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #000; + opacity: 0; + visibility: hidden; + z-index: 16384; + transition: all 0.3s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#lockscreen.visible { + opacity: 1; + visibility: visible; +} + +#lockscreen-background { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: linear-gradient(to bottom, #00240c, rgb(0, 26, 42)) , url(/resources/wallpapers/default.png) no-repeat center / cover; + transform: scale(calc(1 + (0.125 * (1 - (1 - var(--motion-progress, 1)))))); +} + +#lockscreen.transitioning #lockscreen-background { + transition: all 0.3s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#lockscreen.low-power #lockscreen-background { + opacity: 0; + visibility: hidden; + transition: all 1s ease; +} + +#lockscreen-container { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; +} + +.lockscreen-row { + width: 100%; + display: flex; + flex-direction: column; + margin: 1.5rem 0; + align-items: center; + transform: scale(calc(1 - (0.125 * (1 - var(--motion-progress, 1))))); + opacity: var(--motion-progress, 1); +} + +#lockscreen.transitioning .lockscreen-row { + transition: all 0.3s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#lockscreen.low-power .lockscreen-row { + margin: 3rem 0 0; + opacity: 0.75; + transition: all 1s ease; +} + +#lockscreen-icon { + margin: 4.5rem 0 0; + color: #fff; + text-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.3); +} + +#lockscreen-icon.fail-unlock { + animation: fail-unlock 0.75s ease-in-out; +} + +@keyframes fail-unlock { + 0% { + transform: translateX(0); + } + 20% { + transform: translateX(1rem); + } + 40% { + transform: translateX(-0.75rem); + } + 60% { + transform: translateX(0.5rem); + } + 80% { + transform: translateX(-0.25rem); + } + 100% { + transform: translateX(0); + } +} + +#lockscreen-clock { + font-size: 7.2rem; + font-weight: normal; + color: #fff; + line-height: 7.8rem; + text-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.3); +} + +#lockscreen-date { + font-size: 2rem; + color: #fff; + text-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.3); +} + +.lockscreen-hint { + position: absolute; + left: 0; + width: 100%; + bottom: calc(25% * (1 - var(--motion-progress, 1))); + text-align: center; + padding: 0 1.5rem 2.5rem; + box-sizing: border-box; + pointer-events: none; + font-size: 1.6rem; + color: rgba(255, 255, 255, calc(var(--motion-progress, 1) * 0.5)); +} + +#lockscreen.transitioning .lockscreen-hint { + transition: all 0.3s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#lockscreen.low-power .lockscreen-hint { + opacity: 0.75; + color: transparent; + transition: all 1s ease; +} + +.lockscreen-hint::before { + content: ''; + position: absolute; + left: calc(100% / 3); + width: calc(100% / 3); + bottom: 1rem; + height: 0.5rem; + background-color: #fff; + border-radius: 0.5rem; + box-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.3); +} diff --git a/style/media_playback.css b/style/media_playback.css new file mode 100644 index 0000000..0391037 --- /dev/null +++ b/style/media_playback.css @@ -0,0 +1,66 @@ +#media-playback { + width: 100%; + flex-grow: 1; + background-color: var(--background-plus); + border-radius: 2rem; + min-height: 6.5rem; + position: relative; +} + +#media-playback .content { + width: 100%; + position: absolute; + left: 0; + bottom: 0; + padding: 1rem; + box-sizing: border-box; + color: var(--text-color); +} + +#media-playback-title { + font-size: 1.5rem; + color: var(--text-color); + line-height: 2.1rem; +} + +#media-playback-author { + font-size: 1.3rem; + color: var(--text-color); + line-height: 1.9rem; + opacity: 0.5; +} + +#media-playback .content .buttons { + width: 100%; + height: 3.2rem; + display: flex; + gap: 0.8rem; + justify-content: center; + margin: 0.5rem 0 0; +} + +#media-playback .content .buttons button { + width: 3.2rem; + height: 3.2rem; + line-height: 3.2rem; + background-color: var(--item-hover); + border-radius: 1.6rem; + color: var(--text-color); + text-align: center; + margin: 0; + padding: 0; + flex-shrink: 0; + border: none; +} + +#media-playback .content .buttons button:hover { + background-color: var(--item-hover-plus); +} + +#media-playback .content .buttons button:active { + background-color: var(--item-active-plus); +} + +#media-playback .content .buttons button::before { + font-size: 2rem; +} diff --git a/style/notifications.css b/style/notifications.css new file mode 100644 index 0000000..5bf1c37 --- /dev/null +++ b/style/notifications.css @@ -0,0 +1,152 @@ +#notification-toaster { + position: absolute; + left: 0; + top: var(--statusbar-height); + width: calc(100% - 2rem); + margin: 0 1rem; + background-color: var(--acrylic-background-plus); + backdrop-filter: blur(20px) saturate(180%); + box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.3); + z-index: 32768; + transform: translateY(calc(-100% - var(--statusbar-height) - 4.5rem)); + transition: all 0.5s cubic-bezier(0.8, 0.1, 0.9, 0); +} + +#notification-toaster.visible { + transform: translateY(0); + transition: all 0.5s cubic-bezier(0.2, 0.9, 0.1, 1.1); +} + +.notification { + background-color: var(--background-plus); + border-radius: 2rem; + width: 100%; + margin: 0 0 1rem; +} + +.notification .titlebar { + width: 100%; + padding: 1rem 1.5rem; + box-sizing: border-box; + display: flex; + align-items: center; +} + +.notification .titlebar .badge { + width: 2rem; + height: 2rem; + margin-inline-end: 1rem; + flex-shrink: 0; +} + +.notification .titlebar .source-name { + height: 2rem; + line-height: 2rem; + margin-inline-end: 1rem; + color: var(--text-color); + font-size: 1.4rem; + flex-grow: 1; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + width: 100%; +} + +.notification .content { + width: 100%; + padding: 0 1.5rem 1rem; + box-sizing: border-box; + display: flex; + align-items: center; +} + +.notification .content .icon { + width: 4.5rem; + height: 4.5rem; + margin-inline-end: 1rem; + flex-shrink: 0; +} + +.notification .content .text-holder { + color: var(--text-color); + flex-grow: 1; + display: flex; + flex-direction: column; + width: 100%; + overflow: hidden; +} + +.notification .content .text-holder .title { + color: var(--text-color); + font-size: 1.6rem; + line-height: 2.2rem; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + width: 100%; +} + +.notification .content .text-holder .detail { + color: var(--text-color); + font-size: 1.4rem; + line-height: 2rem; + opacity: 0.5; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + width: 100%; +} + +.notification .media { + width: 100%; + aspect-ratio: 16 / 9; + display: grid; + grid-template-columns: repeat(auto-fit, 1fr); + grid-template-rows: repeat(auto-fit, 1fr); + padding: 0 1.5rem 1rem; + box-sizing: border-box; +} + +.notification .media:empty { + display: none; +} + +.notification .media > img { + object-fit: cover; + width: 100%; + height: 100%; +} + +.notification .actions { + width: 100%; + padding: 0 1.5rem 1rem; + box-sizing: border-box; + display: flex; + align-items: center; + gap: 1rem; +} + +.notification .actions button { + padding: 0 1.5rem; + box-sizing: border-box; + height: 3rem; + line-height: 3rem; + border-radius: 1.5rem; + border: none; + background-color: transparent; + color: var(--text-color); + font-size: 1.6rem; +} + +.notification .actions button:hover { + background-color: var(--item-hover); +} + +.notification .actions button:active { + background-color: var(--item-active); +} + +.notification .actions button.recommend { + background-color: var(--accent-color); + color: var(--accent-color-plus); +} diff --git a/style/quick_settings.css b/style/quick_settings.css new file mode 100644 index 0000000..d566fb3 --- /dev/null +++ b/style/quick_settings.css @@ -0,0 +1,153 @@ +#connection-settings { + width: 100%; + flex-grow: 1; + overflow: hidden; + margin: 0; + padding: 0; + display: flex; + flex-wrap: wrap; + gap: 1rem; +} + +#connection-settings li { + width: 12rem; + flex-grow: 1; + background-color: var(--background-plus); + border-radius: 2rem; + margin: 0; + height: 6.5rem; + list-style: none; +} + +#quick-settings { + width: 100%; + flex-grow: 1; + overflow: hidden; + background-color: var(--background-plus); + border-radius: 2rem; +} + +#quick-settings-grid { + width: 100%; + overflow: hidden; + margin: 0; + padding: 0 1rem; + box-sizing: border-box; + display: flex; + flex-wrap: wrap; + justify-content: space-around; +} + +#quick-settings li { + width: 4rem; + height: 6.5rem; + aspect-ratio: 1 / 1; + list-style: none; +} + +#connection-settings li > a, +#quick-settings li > a { + width: 100%; + height: 100%; + line-height: 1; + display: inline-flex; + align-items: center; + text-decoration: none; + color: var(--text-color); + font-size: 1.4rem; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + padding-inline-start: 6.25rem; + box-sizing: border-box; + position: relative; +} + +#quick-settings li > a { + padding: 0; + padding-inline-start: 0; +} + +#connection-settings li > a[data-icon]::before, +#quick-settings li > a[data-icon]::before { + width: 4rem; + background-color: var(--item-hover); + border-radius: 2rem; + height: 4rem; + line-height: 4rem; + margin: 1.25rem; + text-align: center; + font-size: 2.4rem; + flex-shrink: 0; + position: absolute; + left: 0; + top: 0; +} + +#quick-settings li > a[data-icon]::before { + margin: 1.75rem 0 0.75rem; + position: relative; +} + +#connection-settings li > a::after { + content: ''; + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + border-radius: 2rem; +} + +#connection-settings li > a:hover::after { + background-color: var(--item-hover); +} + +#connection-settings li > a:active::after { + background-color: var(--item-active); +} + +#quick-settings li > a:hover::before { + background-color: var(--item-hover-plus); +} + +#quick-settings li > a:active::before { + background-color: var(--item-active-plus); +} + +#connection-settings li.enabled, +#quick-settings li.enabled > a::before { + background-color: var(--accent-color); + color: var(--accent-color-plus); +} + +#connection-settings li.enabled > a, +#quick-settings li.enabled > a { + color: var(--accent-color-plus); +} + +#connection-settings li.enabled > a { + font-weight: bold; +} + +#connection-settings li.enabled > a[data-icon]::before { + background-color: var(--accent-color-hover); +} + +#quick-settings > .grippy-bar { + width: 100%; + height: 2rem; + position: relative; +} + +#quick-settings > .grippy-bar::before { + content: ''; + position: absolute; + left: 50%; + top: 0.25rem; + width: 5rem; + height: 0.5rem; + margin-left: -2.5rem; + background-color: var(--item-hover); + border-radius: 0.5rem; +} diff --git a/style/software_buttons.css b/style/software_buttons.css new file mode 100644 index 0000000..2d6e30b --- /dev/null +++ b/style/software_buttons.css @@ -0,0 +1,128 @@ +#software-buttons { + position: absolute; + left: 0; + width: 100%; + bottom: 0; + height: var(--software-buttons-height); + display: flex; + justify-content: center; + z-index: 4096; +} + +#screen:not(.keyboard-visible) #software-buttons.light { + filter: invert(1) hue-rotate(180deg); +} + +#software-buttons.hidden { + transform: translateY(-100%); +} + +#software-buttons > button { + position: relative; + width: 8rem; + height: 100%; + background: transparent no-repeat center / 1.75rem; + border: none; + opacity: 0.8; +} + +#software-buttons > button::after { + content: ''; + position: absolute; + left: 50%; + transform: translateX(-50%); + top: 0; + width: 0; + height: 100%; + border-radius: 9999px; + background: rgba(255, 255, 255, 0.1); + opacity: 0; + pointer-events: none; + transition: all 0.3s cubic-bezier(0.2, 0.9, 0.1, 1), width 0.1s ease 0.3s; +} + +#software-buttons > button:active:after { + width: calc(100% + 1rem); + opacity: 1; + transition: all 0.3s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#software-buttons > #software-back-button { + background-image: url(images/back.png); +} + +#software-buttons > #software-home-button { + background-image: url(images/home.png); +} + +#software-buttons > #software-recents-button { + background-image: url(images/recents.png); +} + +#software-buttons > #software-keyboard-button { + background-image: url(images/splitscreen.png); + position: absolute; + top: 0; + right: 0; + width: 5rem; +} + +#dock { + height: var(--software-buttons-height); + display: flex; + padding-inline-start: 2.5rem; + gap: 1.5rem; +} + +#dock .icon { + position: relative; + width: var(--software-buttons-height); + height: var(--software-buttons-height); +} + +#dock .icon.expand { + animation: dock-expand 0.5s cubic-bezier(0.2, 0.9, 0.1, 1) forwards; +} + +@keyframes dock-expand { + from { + transform: scale(0.75); + opacity: 0; + } + to { + transform: scale(1); + opacity: 1; + } +} + +#dock .icon.shrink { + animation: dock-shrink 0.3s cubic-bezier(0.8, 0.1, 0.9, 0) forwards; +} + +@keyframes dock-shrink { + from { + transform: scale(1); + opacity: 1; + } + to { + transform: scale(0.75); + opacity: 0; + } +} + +#dock .icon > img { + width: calc(var(--software-buttons-height) - 1rem); + height: calc(var(--software-buttons-height) - 1rem); + margin: 0.5rem; + opacity: 0.75; +} + +#dock .icon.active > img { + opacity: 1; +} + +@media screen and (max-width: 767px) { + #dock { + display: none; + } +} diff --git a/style/splashscreen.css b/style/splashscreen.css new file mode 100644 index 0000000..8ec9cea --- /dev/null +++ b/style/splashscreen.css @@ -0,0 +1,29 @@ +#splashscreen { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #000; + z-index: 65535; +} + +#splashscreen.hidden { + opacity: 0; + visibility: hidden; + transition: all 0.5s ease 2s; +} + +#splashscreen-video { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + object-fit: cover; +} + +#splashscreen.hidden #splashscreen-video { + transform: scale(0.9); + transition: all 0.5s ease 2s; +} diff --git a/style/statusbar.css b/style/statusbar.css new file mode 100644 index 0000000..7fccc02 --- /dev/null +++ b/style/statusbar.css @@ -0,0 +1,143 @@ +#statusbar { + position: fixed; + left: 0; + top: 0; + width: 100%; + height: var(--statusbar-height); + z-index: 32767; + transition: all 0.3s ease; +} + +#statusbar.light { + filter: invert(1) hue-rotate(180deg); +} + +#statusbar.hidden { + transform: translateY(-100%); +} + +.statusbar-icons { + position: absolute; + left: 0; + top: 0; + margin: 0 var(--statusbar-padding-left) 0 var(--statusbar-padding-right); + width: calc(100% - var(--statusbar-padding-left) - var(--statusbar-padding-right)); + height: 100%; + opacity: 0.8; +} + +.statusbar-icons > .left { + position: absolute; + left: 0; + top: 0; + width: 50%; + height: 100%; + display: flex; + justify-content: start; + align-items: center; +} + +.statusbar-icons > .right { + position: absolute; + left: 50%; + top: 0; + width: 50%; + height: 100%; + display: flex; + justify-content: end; + flex-direction: row-reverse; + align-items: center; +} + +.statusbar-icons > .left div, +.statusbar-icons > .right div { + color: #fff; + min-width: 2rem; + height: 2rem; + line-height: 2rem; + margin: 0 0.2rem; + text-align: center; + transition: all 0.3s cubic-bezier(0.2, 0.9, 0.1, 1.25) 0.3s, margin 0.3s cubic-bezier(0.2, 0.9, 0.1, 1.25); +} + +.statusbar-icons > .left .hidden, +.statusbar-icons > .right .hidden { + opacity: 0; + transform: scale(0.2); + visibility: hidden; + margin: 0 -1rem; + transition: all 0.3s ease, margin 0.3s cubic-bezier(0.2, 0.9, 0.1, 1) 0.3s; +} + +#statusbar-notifications::before { + width: 2rem; + height: 2rem; + line-height: 2rem; + font-size: 1.8rem; +} + +#statusbar-time { + color: #fff; + font-size: 1.6rem; +} + +#statusbar-battery::before { + width: 2rem; + height: 2rem; + line-height: 2rem; + font-size: 1.8rem; +} + +#statusbar-cellular-signal { + position: relative; +} + +#statusbar-cellular-signal::before { + position: absolute; + left: 0; + top: 0; + width: 2rem; + height: 2rem; + line-height: 2rem; + font-size: 1.8rem; +} + +#statusbar-cellular-signal::after { + content: 'signal-5'; + position: absolute; + left: 0; + top: 0; + font-family: "openorchid-icons"; + width: 2rem; + height: 2rem; + line-height: 2rem; + font-size: 1.8rem; + opacity: 0.5; +} + +#statusbar-network { + position: relative; +} + +#statusbar-network::before { + position: absolute; + left: 0; + top: 0; + width: 2rem; + height: 2rem; + line-height: 2rem; + font-size: 1.8rem; +} + +#statusbar-network::after { + content: 'wifi-4'; + position: absolute; + left: 0; + top: 0; + font-family: "openorchid-icons"; + width: 2rem; + height: 2rem; + line-height: 2rem; + font-size: 1.8rem; + opacity: 0.5; +} diff --git a/style/system.css b/style/system.css new file mode 100644 index 0000000..4d322d7 --- /dev/null +++ b/style/system.css @@ -0,0 +1,47 @@ +html, body { + +@import url('https://fonts.googleapis.com/css2?family=Readex+Pro:wght@400;500;600&display=swap'); + +* { + margin: 0; + padding: 0; + font-family: "Readex Pro", sans-serif; +} + + margin: 0; + padding: 0; + font-size: 10px; + -webkit-tap-highlight-color: transparent; +} + +#screen { + --statusbar-height: 4rem; + --statusbar-padding-left: 3rem; + --statusbar-padding-right: 3rem; + --software-buttons-height: 4rem; + --screen-radius: 3.6rem; + --chrome-toolbar-gap: 0.5rem; + --chrome-tablist-height: 4rem; + --chrome-navbar-height: 4rem; + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: linear-gradient(to bottom, #00240c, rgb(0, 26, 42)) , url(/resources/wallpapers/default.png) no-repeat center / cover; + +} + +#screen ::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +#screen ::-webkit-scrollbar-thumb { + background-color: #858585; + background-clip: content-box; + border: 2px solid transparent; + border-radius: 8px; + width: 8px; + height: 8px; +} diff --git a/style/things/buttons.css b/style/things/buttons.css new file mode 100644 index 0000000..e03126b --- /dev/null +++ b/style/things/buttons.css @@ -0,0 +1,34 @@ +.ripple-button { + position: relative; + overflow: hidden; + display: inline-block; + cursor: pointer; +} + +.ripple { + content: ""; + display: block; + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + background: radial-gradient(circle at 50% 50%, rgba(0, 0, 0, 0.2), transparent 75%); + border-radius: 50%; + pointer-events: none; +} + +.ripple.animate { + animation: rippleEffect 0.75s ease forwards; +} + +@keyframes rippleEffect { + 0% { + opacity: 1; + transform: scale(0); + } + 100% { + opacity: 0; + transform: scale(1); + } +} diff --git a/style/things/fonts.css b/style/things/fonts.css new file mode 100644 index 0000000..5f61b22 --- /dev/null +++ b/style/things/fonts.css @@ -0,0 +1,51 @@ +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-ExtraLight.ttf); + font-weight: 200; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Light.ttf); + font-weight: 300; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Regular.ttf); + font-weight: 400; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Medium.ttf); + font-weight: 500; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-SemiBold.ttf); + font-weight: 600; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Bold.ttf); + font-weight: 700; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-ExtraBold.ttf); + font-weight: 800; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Black.ttf); + font-weight: 900; +} + +*, ::placeholder { + font-family: 'Jali Arabic'; +} diff --git a/style/things/headerbars.css b/style/things/headerbars.css new file mode 100644 index 0000000..9c2710c --- /dev/null +++ b/style/things/headerbars.css @@ -0,0 +1,79 @@ +.headerbar { + width: 100%; + height: calc(var(--statusbar-height) + 5rem + (4rem * (1 - var(--progress, 0)))); + background-color: rgba(var(--headerbar-r), var(--headerbar-g), var(--headerbar-b), calc(var(--progress, 0) * 0.75)); + display: flex; + padding: var(--statusbar-height) 1rem 0; + box-sizing: border-box; + z-index: 10; + flex-shrink: 0; + backdrop-filter: blur(20px) saturate(calc(100% + (80% * var(--progress, 0)))); +} + +.headerbar .safezone { + width: 100%; + max-width: 74.5rem; + margin: 0 auto; + display: flex; +} + +.headerbar h1 { + flex-grow: 1; + margin: 0; + padding: 0 1rem; + box-sizing: border-box; + height: calc(5rem - (1rem * (1 - var(--progress, 0)))); + line-height: calc(5rem - (1rem * (1 - var(--progress, 0)))); + display: inline-block; + color: var(--text-color); + font-weight: normal; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + transform: translateY(calc(4.5rem * (1 - var(--progress, 0)))); + width: 100%; + font-size: calc(2rem + (0.8rem * (1 - var(--progress, 0)))); +} + +.headerbar a + h1 { + transform: translate(calc(-4rem * (1 - var(--progress, 0))), calc(4.5rem * (1 - var(--progress, 0)))); +} + +.headerbar a { + width: 4rem; + height: 4rem; + text-decoration: none; + line-height: 4rem; + border-radius: 50%; + display: inline-block; + color: var(--text-color); + flex-shrink: 0; + margin: 0.5rem 0; + text-align: center; + padding: 0 1rem; + box-sizing: border-box; +} + +.headerbar a:hover { + background-color: var(--item-hover); +} + +.headerbar a:active { + background-color: var(--item-active); +} + +.headerbar a[data-icon]::before { + width: 2rem; + height: 4rem; + line-height: 4rem; + font-size: 2rem; +} + +.headerbar menu[role="toolbar"] { + display: inline-flex; + height: 5rem; + flex-shrink: 0; + margin: 0; + padding: 0; + /* transform: translate(0, calc(50% * (1 - var(--progress, 0)))); */ +} diff --git a/style/things/icons/fonts/openorchid-icons.eot b/style/things/icons/fonts/openorchid-icons.eot new file mode 100644 index 0000000..92675a1 Binary files /dev/null and b/style/things/icons/fonts/openorchid-icons.eot differ diff --git a/style/things/icons/fonts/openorchid-icons.svg b/style/things/icons/fonts/openorchid-icons.svg new file mode 100644 index 0000000..5a9e7a0 --- /dev/null +++ b/style/things/icons/fonts/openorchid-icons.svg @@ -0,0 +1,959 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/style/things/icons/fonts/openorchid-icons.ttf b/style/things/icons/fonts/openorchid-icons.ttf new file mode 100644 index 0000000..666be18 Binary files /dev/null and b/style/things/icons/fonts/openorchid-icons.ttf differ diff --git a/style/things/icons/fonts/openorchid-icons.woff b/style/things/icons/fonts/openorchid-icons.woff new file mode 100644 index 0000000..c516071 Binary files /dev/null and b/style/things/icons/fonts/openorchid-icons.woff differ diff --git a/style/things/icons/icons.css b/style/things/icons/icons.css new file mode 100644 index 0000000..a369788 --- /dev/null +++ b/style/things/icons/icons.css @@ -0,0 +1,1454 @@ +/* Generated by grunt-webfont */ +/* Based on https://github.com/endtwist/fontcustom/blob/master/lib/fontcustom/templates/fontcustom.css */ + + +@font-face { + font-family: "openorchid-icons"; + src: url('fonts/openorchid-icons.eot'); + src: url('fonts/openorchid-icons.eot') format('embedded-opentype'), + url('fonts/openorchid-icons.ttf') format('truetype'), + url('fonts/openorchid-icons.woff') format('woff'), + url('fonts/openorchid-icons.svg#openorchid-icons') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + + +[data-icon]:before, +.ligature-icons { + font-family: "openorchid-icons"; + content: attr(data-icon); + display: inline-block; + font-weight: 500; + font-style: normal; + text-decoration: inherit; + text-transform: none; + text-rendering: optimizeLegibility; + font-size: 30px; + -webkit-font-smoothing: antialiased; +} + + +.icon-accessibility:before { + content: "\e900"; +} +.icon-achievement:before { + content: "\e901"; +} +.icon-activecall-bluetooth:before { + content: "\e902"; +} +.icon-activecall-hangup:before { + content: "\e903"; +} +.icon-activecall-hold:before { + content: "\e904"; +} +.icon-activecall-mergecalls:before { + content: "\e905"; +} +.icon-activecall-mute:before { + content: "\e906"; +} +.icon-activecall-pickup:before { + content: "\e907"; +} +.icon-activecall-sms:before { + content: "\e908"; +} +.icon-activecall-speaker:before { + content: "\e909"; +} +.icon-activecall-switchlines:before { + content: "\e90a"; +} +.icon-activecall-voicemail:before { + content: "\e90b"; +} +.icon-add:before { + content: "\e90c"; +} +.icon-addons:before { + content: "\e90d"; +} +.icon-airplane:before { + content: "\e90e"; +} +.icon-alarm-clock:before { + content: "\e90f"; +} +.icon-alarmstop:before { + content: "\e910"; +} +.icon-album:before { + content: "\e911"; +} +.icon-all-day:before { + content: "\e912"; +} +.icon-apps:before { + content: "\e913"; +} +.icon-artist:before { + content: "\e914"; +} +.icon-attachments:before { + content: "\e915"; +} +.icon-audio:before { + content: "\e916"; +} +.icon-auth:before { + content: "\e917"; +} +.icon-auto-enhance-spark:before { + content: "\e918"; +} +.icon-back:before { + content: "\e91a"; +} +.icon-back-light:before { + content: "\e91b"; +} +.icon-battery:before { + content: "\e91c"; +} +.icon-battery-0:before { + content: "\e91d"; +} +.icon-battery-10:before { + content: "\e91e"; +} +.icon-battery-100:before { + content: "\e927"; +} +.icon-battery-20:before { + content: "\e91f"; +} +.icon-battery-30:before { + content: "\e920"; +} +.icon-battery-40:before { + content: "\e921"; +} +.icon-battery-50:before { + content: "\e922"; +} +.icon-battery-60:before { + content: "\e923"; +} +.icon-battery-70:before { + content: "\e924"; +} +.icon-battery-80:before { + content: "\e925"; +} +.icon-battery-90:before { + content: "\e926"; +} +.icon-battery-charging:before { + content: "\e928"; +} +.icon-battery-charging-0:before { + content: "\e929"; +} +.icon-battery-charging-10:before { + content: "\e92a"; +} +.icon-battery-charging-100:before { + content: "\e933"; +} +.icon-battery-charging-20:before { + content: "\e92b"; +} +.icon-battery-charging-30:before { + content: "\e92c"; +} +.icon-battery-charging-40:before { + content: "\e92d"; +} +.icon-battery-charging-50:before { + content: "\e92e"; +} +.icon-battery-charging-60:before { + content: "\e92f"; +} +.icon-battery-charging-70:before { + content: "\e930"; +} +.icon-battery-charging-80:before { + content: "\e931"; +} +.icon-battery-charging-90:before { + content: "\e932"; +} +.icon-bell:before { + content: "\e934"; +} +.icon-bluetooth:before { + content: "\e935"; +} +.icon-bookmark:before { + content: "\e936"; +} +.icon-bookmarked:before { + content: "\e937"; +} +.icon-brightness:before { + content: "\e938"; +} +.icon-browser-back:before { + content: "\e939"; +} +.icon-browser-closecancel:before { + content: "\e93a"; +} +.icon-browser-crashedtab:before { + content: "\e93b"; +} +.icon-browser-forward:before { + content: "\e93c"; +} +.icon-browser-home:before { + content: "\e93d"; +} +.icon-browser-library:before { + content: "\e93e"; +} +.icon-browser-moretabs:before { + content: "\e93f"; +} +.icon-browser-nofavicon:before { + content: "\e940"; +} +.icon-browser-pictureinpicture:before { + content: "\e941"; +} +.icon-browser-readermode:before { + content: "\e942"; +} +.icon-browser-reload:before { + content: "\e943"; +} +.icon-browser-search:before { + content: "\e944"; +} +.icon-browser-secure:before { + content: "\e945"; +} +.icon-browser-secureunverified:before { + content: "\e946"; +} +.icon-browser-sidetabs:before { + content: "\e947"; +} +.icon-browser-tabpreviews:before { + content: "\e948"; +} +.icon-browsing:before { + content: "\e949"; +} +.icon-bug:before { + content: "\e94a"; +} +.icon-calendar-alarm:before { + content: "\e94b"; +} +.icon-calendar-allday:before { + content: "\e94c"; +} +.icon-calendar-bullet:before { + content: "\e94d"; +} +.icon-calendar-dot:before { + content: "\e94e"; +} +.icon-calendar-eventalarm:before { + content: "\e94f"; +} +.icon-calendar-today:before { + content: "\e950"; +} +.icon-call:before { + content: "\e951"; +} +.icon-call-incoming:before { + content: "\e952"; +} +.icon-call-outgoing:before { + content: "\e95c"; +} +.icon-call-ringing:before { + content: "\e95d"; +} +.icon-calllog-checkboxoff:before { + content: "\e953"; +} +.icon-calllog-checkboxon-box:before { + content: "\e954"; +} +.icon-calllog-checkboxon-checkmark:before { + content: "\e955"; +} +.icon-calllog-expand:before { + content: "\e956"; +} +.icon-calllog-incomingcall:before { + content: "\e957"; +} +.icon-calllog-incomingsms:before { + content: "\e958"; +} +.icon-calllog-missedcall:before { + content: "\e959"; +} +.icon-calllog-outgoingcall:before { + content: "\e95a"; +} +.icon-calllog-outgoingsms:before { + content: "\e95b"; +} +.icon-camera:before { + content: "\e95e"; +} +.icon-camera-cameraorientation:before { + content: "\e95f"; +} +.icon-camera-flashauto:before { + content: "\e960"; +} +.icon-camera-flashoff:before { + content: "\e961"; +} +.icon-camera-flashon:before { + content: "\e962"; +} +.icon-camera-videorecorder:before { + content: "\e963"; +} +.icon-change-wallpaper:before { + content: "\e964"; +} +.icon-checked:before { + content: "\e965"; +} +.icon-clear-all:before { + content: "\e966"; +} +.icon-clearcancel-circle:before { + content: "\e967"; +} +.icon-clearcancel-cross:before { + content: "\e968"; +} +.icon-close:before { + content: "\e969"; +} +.icon-closecancel:before { + content: "\e96a"; +} +.icon-collapse-chevron:before { + content: "\e96b"; +} +.icon-compose:before { + content: "\e96c"; +} +.icon-contact-add:before { + content: "\e96d"; +} +.icon-contact-addfavorite:before { + content: "\e96e"; +} +.icon-contact-addimage:before { + content: "\e96f"; +} +.icon-contact-checkmark:before { + content: "\e970"; +} +.icon-contact-delete-circle:before { + content: "\e971"; +} +.icon-contact-delete-minus:before { + content: "\e972"; +} +.icon-contact-detailfacebook-f:before { + content: "\e973"; +} +.icon-contact-detailfacebook-square:before { + content: "\e974"; +} +.icon-contact-email:before { + content: "\e975"; +} +.icon-contact-favorite:before { + content: "\e976"; +} +.icon-contact-favorited:before { + content: "\e977"; +} +.icon-contact-favoritedcontact:before { + content: "\e978"; +} +.icon-contact-find:before { + content: "\e979"; +} +.icon-contact-link:before { + content: "\e97a"; +} +.icon-contact-location:before { + content: "\e97b"; +} +.icon-contact-phone:before { + content: "\e97c"; +} +.icon-contact-sms:before { + content: "\e97e"; +} +.icon-contact-twitter:before { + content: "\e97f"; +} +.icon-contact-undo-roundarrow:before { + content: "\e981"; +} +.icon-contacts:before { + content: "\e97d"; +} +.icon-copy:before { + content: "\e982"; +} +.icon-costcontrol-topup:before { + content: "\e983"; +} +.icon-costcontrol-topuppay:before { + content: "\e984"; +} +.icon-costcontrol-topupwithcode:before { + content: "\e985"; +} +.icon-costcontrol-updatebalance:before { + content: "\e986"; +} +.icon-crop:before { + content: "\e987"; +} +.icon-cut:before { + content: "\e988"; +} +.icon-data:before { + content: "\e989"; +} +.icon-database:before { + content: "\e98a"; +} +.icon-delete:before { + content: "\e98b"; +} +.icon-desktop:before { + content: "\e98c"; +} +.icon-developer:before { + content: "\e98d"; +} +.icon-dialer-contacts:before { + content: "\e98e"; +} +.icon-dialer-delete:before { + content: "\e98f"; +} +.icon-dialer-dialpad:before { + content: "\e990"; +} +.icon-dialer-recentcalls:before { + content: "\e991"; +} +.icon-dialpad:before { + content: "\e992"; +} +.icon-discord:before { + content: "\e993"; +} +.icon-dislike:before { + content: "\e994"; +} +.icon-disliked:before { + content: "\e995"; +} +.icon-dismisskeyboard:before { + content: "\e996"; +} +.icon-display:before { + content: "\e997"; +} +.icon-do-not-track:before { + content: "\e998"; +} +.icon-download:before { + content: "\e999"; +} +.icon-download-circle:before { + content: "\e99a"; +} +.icon-edit:before { + content: "\e99b"; +} +.icon-edit-image:before { + content: "\e99d"; +} +.icon-editcontact:before { + content: "\e99c"; +} +.icon-eject:before { + content: "\e99e"; +} +.icon-email:before { + content: "\e99f"; +} +.icon-email-addrecipient-circle:before { + content: "\e9a0"; +} +.icon-email-addrecipient-plus:before { + content: "\e9a1"; +} +.icon-email-attachment:before { + content: "\e9a2"; +} +.icon-email-downloadattachment:before { + content: "\e9a3"; +} +.icon-email-flag:before { + content: "\e9a4"; +} +.icon-email-forward:before { + content: "\e9a5"; +} +.icon-email-markread:before { + content: "\e9a6"; +} +.icon-email-markunread:before { + content: "\e9a7"; +} +.icon-email-move:before { + content: "\e9a8"; +} +.icon-email-removeattachment-circle:before { + content: "\e9a9"; +} +.icon-email-removeattachment-cross:before { + content: "\e9aa"; +} +.icon-email-reply:before { + content: "\e9ab"; +} +.icon-email-replyall:before { + content: "\e9ac"; +} +.icon-email-send:before { + content: "\e9ad"; +} +.icon-emailsmscalilog-editlist:before { + content: "\e9ae"; +} +.icon-emojis:before { + content: "\e9af"; +} +.icon-eraser:before { + content: "\e9b0"; +} +.icon-expand:before { + content: "\e9b1"; +} +.icon-expand-chevron:before { + content: "\e9b2"; +} +.icon-export:before { + content: "\e9b3"; +} +.icon-face-recognition:before { + content: "\e9b5"; +} +.icon-face-recognition-fail:before { + content: "\e9b6"; +} +.icon-facebook:before { + content: "\e9b4"; +} +.icon-favorites:before { + content: "\e9b7"; +} +.icon-feedback:before { + content: "\e9b8"; +} +.icon-file:before { + content: "\e9b9"; +} +.icon-find:before { + content: "\e9ba"; +} +.icon-fingerprint:before { + content: "\e9bb"; +} +.icon-firefox:before { + content: "\e9bc"; +} +.icon-flag:before { + content: "\e9bd"; +} +.icon-flashlight:before { + content: "\e9be"; +} +.icon-fm-favouritedstation:before { + content: "\e9bf"; +} +.icon-fm-sound:before { + content: "\e9c0"; +} +.icon-folder:before { + content: "\e9c1"; +} +.icon-forbidden:before { + content: "\e9c2"; +} +.icon-forward:before { + content: "\e9c3"; +} +.icon-forward-light:before { + content: "\e9c4"; +} +.icon-ftu-importgmail:before { + content: "\e9c5"; +} +.icon-ftu-importoutlook:before { + content: "\e9c6"; +} +.icon-ftu-importsdcard:before { + content: "\e9c7"; +} +.icon-ftu-importsim:before { + content: "\e9c8"; +} +.icon-fullscreen:before { + content: "\e9c9"; +} +.icon-fullscreen-exit:before { + content: "\e9ca"; +} +.icon-gallery-autoenhancespark:before { + content: "\e9cb"; +} +.icon-gallery-crop:before { + content: "\e9cd"; +} +.icon-gallery-crop-photo:before { + content: "\e9d2"; +} +.icon-gallery-crop1x1-mark:before { + content: "\e9ce"; +} +.icon-gallery-crop2x3-mark:before { + content: "\e9cf"; +} +.icon-gallery-crop3x2-mark:before { + content: "\e9d0"; +} +.icon-gallery-cropfree-mark:before { + content: "\e9d1"; +} +.icon-gallery-exposure:before { + content: "\e9d3"; +} +.icon-gallery-filterscircleopacity100:before { + content: "\e9d6"; +} +.icon-gallery-filterscircleopacity35:before { + content: "\e9d4"; +} +.icon-gallery-filterscircleopacity50:before { + content: "\e9d5"; +} +.icon-gallery-rotate:before { + content: "\e9d7"; +} +.icon-game:before { + content: "\e9d8"; +} +.icon-gerneral-unlock:before { + content: "\e9d9"; +} +.icon-gesture:before { + content: "\e9da"; +} +.icon-gmail:before { + content: "\e9db"; +} +.icon-google:before { + content: "\e9dc"; +} +.icon-grid:before { + content: "\e9dd"; +} +.icon-heart:before { + content: "\e9de"; +} +.icon-help:before { + content: "\e9df"; +} +.icon-history:before { + content: "\e9e0"; +} +.icon-home:before { + content: "\e9e1"; +} +.icon-homescreen:before { + content: "\e9e2"; +} +.icon-homescreendelete-circle:before { + content: "\e9e3"; +} +.icon-homescreendelete-cross:before { + content: "\e9e4"; +} +.icon-info:before { + content: "\e9e5"; +} +.icon-instagram:before { + content: "\e9e6"; +} +.icon-iris-scanner:before { + content: "\e9e7"; +} +.icon-iris-scanner-fail:before { + content: "\e9e8"; +} +.icon-iris-scanner-success:before { + content: "\e9e9"; +} +.icon-keyboard:before { + content: "\e9ea"; +} +.icon-keyboard-circle:before { + content: "\e9eb"; +} +.icon-languages:before { + content: "\e9ec"; +} +.icon-left:before { + content: "\e9ed"; +} +.icon-left-light:before { + content: "\e9ee"; +} +.icon-library:before { + content: "\e9ef"; +} +.icon-like:before { + content: "\e9f0"; +} +.icon-liked:before { + content: "\e9f1"; +} +.icon-link:before { + content: "\e9f2"; +} +.icon-linkedin:before { + content: "\e9f3"; +} +.icon-location:before { + content: "\e9f4"; +} +.icon-lock:before { + content: "\e9f5"; +} +.icon-logout:before { + content: "\e9f6"; +} +.icon-media-camera:before { + content: "\e9f7"; +} +.icon-media-info:before { + content: "\e9f8"; +} +.icon-media-pause:before { + content: "\e9f9"; +} +.icon-media-play:before { + content: "\e9fa"; +} +.icon-media-playcircle:before { + content: "\e9fb"; +} +.icon-media-repeatinfinite:before { + content: "\e9fc"; +} +.icon-media-repeatonce:before { + content: "\e9fd"; +} +.icon-media-seekbackward:before { + content: "\e9fe"; +} +.icon-media-seekforward:before { + content: "\e9ff"; +} +.icon-media-shuffle:before { + content: "\ea00"; +} +.icon-media-skipbackward:before { + content: "\ea01"; +} +.icon-media-skipforward:before { + content: "\ea02"; +} +.icon-media-songs:before { + content: "\ea03"; +} +.icon-media-stop:before { + content: "\ea04"; +} +.icon-media-storage:before { + content: "\ea05"; +} +.icon-menu:before { + content: "\ea06"; +} +.icon-messages:before { + content: "\ea07"; +} +.icon-mic:before { + content: "\ea08"; +} +.icon-miscellaneous-editimage:before { + content: "\ea09"; +} +.icon-miscellaneous-select:before { + content: "\ea0a"; +} +.icon-miscellaneous-undo:before { + content: "\ea0b"; +} +.icon-moderator:before { + content: "\ea0c"; +} +.icon-moon:before { + content: "\ea0d"; +} +.icon-more:before { + content: "\ea0e"; +} +.icon-music-album:before { + content: "\ea0f"; +} +.icon-music-artist:before { + content: "\ea10"; +} +.icon-music-gridview:before { + content: "\ea11"; +} +.icon-music-playlist:before { + content: "\ea12"; +} +.icon-newadd:before { + content: "\ea13"; +} +.icon-nfc:before { + content: "\ea14"; +} +.icon-notification-bluetooth:before { + content: "\ea15"; +} +.icon-notification-bluetoothtransfer:before { + content: "\ea16"; +} +.icon-notification-cameramic:before { + content: "\ea17"; +} +.icon-notification-cameraon:before { + content: "\ea18"; +} +.icon-notification-circle:before { + content: "\ea19"; +} +.icon-notification-download:before { + content: "\ea1a"; +} +.icon-notification-downloadfailed-exclamation:before { + content: "\ea1b"; +} +.icon-notification-facebook:before { + content: "\ea1c"; +} +.icon-notification-importingfrommemorycard:before { + content: "\ea1d"; +} +.icon-notification-lowstorage:before { + content: "\ea1e"; +} +.icon-notification-mic:before { + content: "\ea1f"; +} +.icon-notifications:before { + content: "\ea20"; +} +.icon-options:before { + content: "\ea21"; +} +.icon-outlook:before { + content: "\ea22"; +} +.icon-paintbrush:before { + content: "\ea23"; +} +.icon-paintbucket:before { + content: "\ea24"; +} +.icon-paste:before { + content: "\ea25"; +} +.icon-pause:before { + content: "\ea26"; +} +.icon-permissions:before { + content: "\ea27"; +} +.icon-phone:before { + content: "\ea28"; +} +.icon-picture-in-picture:before { + content: "\ea29"; +} +.icon-pin:before { + content: "\ea2a"; +} +.icon-play:before { + content: "\ea2b"; +} +.icon-play-circle:before { + content: "\ea2c"; +} +.icon-playlist:before { + content: "\ea2d"; +} +.icon-power:before { + content: "\ea2e"; +} +.icon-qr:before { + content: "\ea2f"; +} +.icon-qr-scan:before { + content: "\ea30"; +} +.icon-quote:before { + content: "\ea31"; +} +.icon-reader-mode:before { + content: "\ea32"; +} +.icon-recent-calls:before { + content: "\ea33"; +} +.icon-redo:before { + content: "\ea34"; +} +.icon-reload:before { + content: "\ea35"; +} +.icon-repeat:before { + content: "\ea36"; +} +.icon-repeat-once:before { + content: "\ea37"; +} +.icon-right:before { + content: "\ea38"; +} +.icon-right-light:before { + content: "\ea39"; +} +.icon-save:before { + content: "\ea3a"; +} +.icon-sdcard:before { + content: "\ea3b"; +} +.icon-search:before { + content: "\ea3c"; +} +.icon-select:before { + content: "\ea3d"; +} +.icon-selectall:before { + content: "\ea3e"; +} +.icon-send:before { + content: "\ea3f"; +} +.icon-settings:before { + content: "\ea40"; +} +.icon-settings-aboutphone:before { + content: "\ea41"; +} +.icon-settings-accessibility:before { + content: "\ea42"; +} +.icon-settings-airplane:before { + content: "\ea43"; +} +.icon-settings-app-permissions:before { + content: "\ea44"; +} +.icon-settings-apps:before { + content: "\ea45"; +} +.icon-settings-appstorage:before { + content: "\ea46"; +} +.icon-settings-battery:before { + content: "\ea47"; +} +.icon-settings-bluetooth:before { + content: "\ea48"; +} +.icon-settings-brightness:before { + content: "\ea49"; +} +.icon-settings-brightness-lower:before { + content: "\ea4a"; +} +.icon-settings-call:before { + content: "\ea4b"; +} +.icon-settings-camera-permissions:before { + content: "\ea4c"; +} +.icon-settings-changewallpapericon:before { + content: "\ea4e"; +} +.icon-settings-contacts-permissions:before { + content: "\ea4f"; +} +.icon-settings-developer:before { + content: "\ea50"; +} +.icon-settings-deviceinfo:before { + content: "\ea51"; +} +.icon-settings-devicestorage-permissions:before { + content: "\ea52"; +} +.icon-settings-display:before { + content: "\ea53"; +} +.icon-settings-donottrack:before { + content: "\ea54"; +} +.icon-settings-download:before { + content: "\ea55"; +} +.icon-settings-email:before { + content: "\ea56"; +} +.icon-settings-facerecognition:before { + content: "\ea57"; +} +.icon-settings-feedback:before { + content: "\ea58"; +} +.icon-settings-findmydevice:before { + content: "\ea59"; +} +.icon-settings-fingerprint:before { + content: "\ea5a"; +} +.icon-settings-fmradio-permissions:before { + content: "\ea5b"; +} +.icon-settings-gesture:before { + content: "\ea5c"; +} +.icon-settings-gps:before { + content: "\ea5d"; +} +.icon-settings-gps-permissions:before { + content: "\ea5e"; +} +.icon-settings-help:before { + content: "\ea5f"; +} +.icon-settings-helpx:before { + content: "\ea60"; +} +.icon-settings-homescreen:before { + content: "\ea61"; +} +.icon-settings-irisscanner:before { + content: "\ea62"; +} +.icon-settings-languages:before { + content: "\ea63"; +} +.icon-settings-mediastorage:before { + content: "\ea64"; +} +.icon-settings-messages:before { + content: "\ea65"; +} +.icon-settings-network:before { + content: "\ea66"; +} +.icon-settings-nfc:before { + content: "\ea67"; +} +.icon-settings-notifications:before { + content: "\ea68"; +} +.icon-settings-persona:before { + content: "\ea69"; +} +.icon-settings-phonelock:before { + content: "\ea6a"; +} +.icon-settings-privacy:before { + content: "\ea6b"; +} +.icon-settings-simcardlock:before { + content: "\ea6c"; +} +.icon-settings-simtoolkit:before { + content: "\ea6d"; +} +.icon-settings-sound-max:before { + content: "\ea6e"; +} +.icon-settings-sound-min:before { + content: "\ea6f"; +} +.icon-settings-tethering:before { + content: "\ea70"; +} +.icon-settings-themes:before { + content: "\ea71"; +} +.icon-settings-time:before { + content: "\ea72"; +} +.icon-settings-usbstorage:before { + content: "\ea73"; +} +.icon-settings-wallpaper:before { + content: "\ea74"; +} +.icon-settings-wifi:before { + content: "\ea75"; +} +.icon-settings-wifi-1:before { + content: "\ea76"; +} +.icon-settings-wifi-2:before { + content: "\ea77"; +} +.icon-settings-wifi-3:before { + content: "\ea78"; +} +.icon-settings-wifi-4:before { + content: "\ea79"; +} +.icon-settings-wifi-lock:before { + content: "\ea7a"; +} +.icon-settings-wifi-lock-1:before { + content: "\ea7b"; +} +.icon-settings-wifi-lock-2:before { + content: "\ea7c"; +} +.icon-settings-wifi-lock-3:before { + content: "\ea7d"; +} +.icon-settings-wifi-lock-4:before { + content: "\ea7e"; +} +.icon-settings-wifi-permissions:before { + content: "\ea7f"; +} +.icon-share:before { + content: "\ea80"; +} +.icon-shopping-cart:before { + content: "\ea81"; +} +.icon-shuffle:before { + content: "\ea82"; +} +.icon-side-tabs:before { + content: "\ea83"; +} +.icon-signal-1:before { + content: "\ea84"; +} +.icon-signal-2:before { + content: "\ea85"; +} +.icon-signal-3:before { + content: "\ea86"; +} +.icon-signal-4:before { + content: "\ea87"; +} +.icon-signal-5:before { + content: "\ea88"; +} +.icon-sim:before { + content: "\ea89"; +} +.icon-skip-back:before { + content: "\ea8a"; +} +.icon-skip-forward:before { + content: "\ea8b"; +} +.icon-sms:before { + content: "\ea8c"; +} +.icon-snap-bottom:before { + content: "\ea8d"; +} +.icon-snap-bottom-left:before { + content: "\ea8e"; +} +.icon-snap-bottom-right:before { + content: "\ea8f"; +} +.icon-snap-left:before { + content: "\ea90"; +} +.icon-snap-right:before { + content: "\ea91"; +} +.icon-snap-top:before { + content: "\ea92"; +} +.icon-snap-top-left:before { + content: "\ea93"; +} +.icon-snap-top-right:before { + content: "\ea94"; +} +.icon-songs:before { + content: "\ea95"; +} +.icon-sound-max:before { + content: "\ea96"; +} +.icon-sound-min:before { + content: "\ea97"; +} +.icon-speaker:before { + content: "\ea98"; +} +.icon-splitscreen:before { + content: "\ea99"; +} +.icon-spotify-svgrepo-com:before { + content: "\ea9a"; +} +.icon-ssl:before { + content: "\ea9b"; +} +.icon-ssl-broken:before { + content: "\ea9c"; +} +.icon-stickers:before { + content: "\ea9d"; +} +.icon-storage:before { + content: "\ea9e"; +} +.icon-sync:before { + content: "\ea9f"; +} +.icon-tab-previews:before { + content: "\eaa1"; +} +.icon-tablet:before { + content: "\eaa0"; +} +.icon-taskswitcherappclose-circle:before { + content: "\eaa2"; +} +.icon-taskswitcherappclose-cross:before { + content: "\eaa3"; +} +.icon-television:before { + content: "\eaa4"; +} +.icon-tethering:before { + content: "\eaa5"; +} +.icon-textselection-copy:before { + content: "\eaa6"; +} +.icon-textselection-cut:before { + content: "\eaa7"; +} +.icon-textselection-paste:before { + content: "\eaa8"; +} +.icon-textselection-selectall:before { + content: "\eaa9"; +} +.icon-themes:before { + content: "\eaaa"; +} +.icon-threadnotsent-circle:before { + content: "\eaab"; +} +.icon-threadnotsent-exclamation:before { + content: "\eaac"; +} +.icon-tick:before { + content: "\eaad"; +} +.icon-tick-circle:before { + content: "\eaae"; +} +.icon-tiktok:before { + content: "\eaaf"; +} +.icon-time:before { + content: "\eab0"; +} +.icon-treadsent-check:before { + content: "\eab1"; +} +.icon-treadsent-circle:before { + content: "\eab2"; +} +.icon-tree:before { + content: "\eab3"; +} +.icon-tv:before { + content: "\eab4"; +} +.icon-twitch:before { + content: "\eab5"; +} +.icon-twitter:before { + content: "\eab6"; +} +.icon-undo:before { + content: "\eab7"; +} +.icon-upload:before { + content: "\eab8"; +} +.icon-usb:before { + content: "\eab9"; +} +.icon-user:before { + content: "\eaba"; +} +.icon-useraccoun-headers:before { + content: "\eabb"; +} +.icon-utility-airplanemode:before { + content: "\eabc"; +} +.icon-utility-arrow:before { + content: "\eabd"; +} +.icon-utility-battery:before { + content: "\eabe"; +} +.icon-utility-bluetooth:before { + content: "\eabf"; +} +.icon-utility-brightness:before { + content: "\eac0"; +} +.icon-utility-camera-lockedscreen:before { + content: "\eac1"; +} +.icon-utility-data:before { + content: "\eac2"; +} +.icon-utility-flashlight:before { + content: "\eac3"; +} +.icon-utility-maxvolume:before { + content: "\eac4"; +} +.icon-utility-mute-cease:before { + content: "\eac5"; +} +.icon-utility-mute-speaker:before { + content: "\eac6"; +} +.icon-utility-vibrate:before { + content: "\eac7"; +} +.icon-utility-volume:before { + content: "\eac8"; +} +.icon-utility-wifi:before { + content: "\eac9"; +} +.icon-vibrate:before { + content: "\eaca"; +} +.icon-video:before { + content: "\eacb"; +} +.icon-vpn:before { + content: "\eacc"; +} +.icon-wallpaper:before { + content: "\eacd"; +} +.icon-web:before { + content: "\eace"; +} +.icon-wifi:before { + content: "\eacf"; +} +.icon-wifi-1:before { + content: "\ead0"; +} +.icon-wifi-2:before { + content: "\ead1"; +} +.icon-wifi-3:before { + content: "\ead2"; +} +.icon-wifi-4:before { + content: "\ead3"; +} +.icon-windows:before { + content: "\ead4"; +} +.icon-wm-snapbottom:before { + content: "\ead5"; +} +.icon-wm-snapbottomleft:before { + content: "\ead6"; +} +.icon-wm-snapbottomright:before { + content: "\ead7"; +} +.icon-wm-snapleft:before { + content: "\ead8"; +} +.icon-wm-snapright:before { + content: "\ead9"; +} +.icon-wm-snaptop:before { + content: "\eada"; +} +.icon-wm-snaptopleft:before { + content: "\eadb"; +} +.icon-wm-snaptopright:before { + content: "\eadc"; +} +.icon-youtube:before { + content: "\eadd"; +} diff --git a/style/things/lists.css b/style/things/lists.css new file mode 100644 index 0000000..eb62410 --- /dev/null +++ b/style/things/lists.css @@ -0,0 +1,122 @@ +.lists header { + width: 100%; + max-width: 74.8rem; + padding: 0 2rem; + box-sizing: border-box; + height: 3rem; + line-height: 3rem; + color: #858585; + font-size: 1.6rem; + font-weight: bold; + text-transform: uppercase; + margin: 1rem auto 0; +} + +.lists ul { + margin: 0 auto 1.5rem; + padding: 0.5rem; + background-color: var(--background-plus); + border-radius: 1.5rem; + width: calc(100% - 3rem); + max-width: 71.8rem; + box-sizing: border-box; +} + +.lists ul li { + position: relative; + margin: 0; + list-style: none; + min-height: 5rem; + display: inline-flex; + flex-direction: column; + justify-content: center; + width: 100%; + padding: 0 1.5rem; + box-sizing: border-box; + border-radius: 1rem; + color: var(--text-color); +} + +.lists ul li:hover { + background-color: var(--item-hover); +} + +.lists ul li:active { + background-color: var(--item-active); +} + +.lists ul li.selected { + background-color: var(--accent-color); + color: var(--accent-color-plus); +} + +.lists ul li[data-icon] { + padding-inline-start: 4.5rem; +} + +.lists ul li[data-icon]::before { + position: absolute; + top: 50%; + margin-top: -1.2rem; + left: 1.2rem; + color: var(--text-color); + width: 2.4rem; + height: 2.4rem; + line-height: 2.4rem; + font-size: 2.4rem; +} + +.lists ul li.selected[data-icon]::before { + color: var(--accent-color-plus); +} + +.lists ul li.page::after { + content: 'forward'; + font-family: "openorchid-icons"; + font-size: 2rem; + color: #858585; + text-align: end; + line-height: 5rem; +} + +.lists ul li.page.selected::after { + color: var(--accent-color-plus); + opacity: 0.5; +} + +.lists ul li::after { + content: ''; + position: absolute; + left: 1.5rem; + top: 0; + width: calc(100% - 3rem); + height: 100%; + pointer-events: none; + border-bottom: solid 0.1rem var(--item-hover); + box-sizing: border-box; +} + +.lists ul li:hover::after, +.lists ul li:active::after, +.lists ul li:last-child::after { + border-bottom: none; +} + +.lists ul li p { + margin: 0; + height: 2.2rem; + line-height: 2.2rem; + font-size: 1.6rem; + color: var(--text-color); +} + +.lists ul li.selected p { + color: var(--accent-color-plus); +} + +.lists ul li p:not(:first-child) { + height: 1.9rem; + line-height: 1.9rem; + font-size: 1.4rem; + opacity: 0.5; +} diff --git a/style/things/main.css b/style/things/main.css new file mode 100644 index 0000000..e2c8636 --- /dev/null +++ b/style/things/main.css @@ -0,0 +1,15 @@ +html, body { + margin: 0; + padding: 0; + font-size: 10px; +} + +.app { + --statusbar-height: 4rem; + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: var(--background); +} diff --git a/style/things/panels.css b/style/things/panels.css new file mode 100644 index 0000000..b05a798 --- /dev/null +++ b/style/things/panels.css @@ -0,0 +1,100 @@ +.panel { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: var(--background); + display: flex; + flex-direction: column; + overflow: hidden; + z-index: 50; +} + +.panel > .content { + width: 100%; + height: 100%; + flex-grow: 1; + overflow-y: auto; + margin-top: calc((-5rem - var(--statusbar-height)) * var(--progress, 0)); + scrollbar-width: none; +} + +.panel > .content aside { + margin: 0 auto 1.5rem; + padding: 0; + background-color: var(--background-minus); + border-radius: 1.5rem; + width: calc(100% - 3rem); + max-width: 71.8rem; + box-sizing: border-box; +} + +.panel > .content aside header { + width: 100%; + padding: 0 2rem; + box-sizing: border-box; + height: 3rem; + line-height: 3rem; + color: #858585; + font-size: 1.6rem; + font-weight: bold; + text-transform: uppercase; + margin: 1rem 0 0; +} + +.panel > .content aside ul { + margin: 0; + padding: 0 0.5rem 0.5rem; + width: 100%; + background-color: transparent; +} + +.panel > .content aside ul li { + min-height: 3.2rem; + background-color: transparent; +} + +.panel > .content aside ul li > a { + color: var(--accent-color); + width: max-content; + line-height: 2.2rem; + font-size: 1.6rem; + text-decoration: none; + transition: box-shadow 0.2s ease; +} + +.panel > .content aside ul li > a:hover { + box-shadow: 0 0.2rem 0 var(--accent-color); +} + +.panel > .content aside ul li > a:active { + opacity: 0.5; +} + +@media screen and (min-width: 983px) { + .panel > .headerbar .safezone { + margin-inline-start: 0; + } + + .panel > .content header, + .panel > .content ul { + margin-inline-start: 1.5rem; + } + + .panel > .content aside { + position: absolute; + right: 0; + top: calc(5rem + var(--statusbar-height) + (4rem * (1 - var(--progress, 0)))); + width: 22rem; + margin: calc(1.5rem * var(--progress, 0)) 1.5rem 1.5rem; + } +} + +@media screen and (min-width: 1536px) { + .panel > .headerbar .safezone, + .panel > .content header, + .panel > .content ul { + margin-inline-start: auto; + } +} diff --git a/style/things/switches.css b/style/things/switches.css new file mode 100644 index 0000000..be56c72 --- /dev/null +++ b/style/things/switches.css @@ -0,0 +1,83 @@ +.pack-switch { + width: 100%; + display: inline-flex; +} + +.pack-switch > label { + width: 100%; + display: inline-flex; + flex-direction: column; + justify-content: center; + flex-grow: 1; +} + +.pack-switch > span { + flex-shrink: 0; + display: inline-flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.pack-switch > span input[type="checkbox"] { + background-color: var(--switch-normal); + width: 5rem; + height: 2.5rem; + border-radius: 2.5rem; + border: none; + position: relative; + outline: none; + appearance: none; + transition: all 0.1s ease; +} + +.pack-switch > span input[type="checkbox"]:hover { + background-color: var(--switch-hover); +} + +.pack-switch > span input[type="checkbox"]:hover { + background-color: var(--switch-active); +} + +.pack-switch > span input[type="checkbox"]:checked { + background-color: var(--accent-color); +} + +.pack-switch > span input[type="checkbox"]::before { + content: ''; + position: absolute; + left: 0.5rem; + top: 0.5rem; + width: 1.5rem; + height: 1.5rem; + background-color: var(--text-color); + border-radius: 1.5rem; + transition: all 0.3s cubic-bezier(0.2, 0, 0, 1); + z-index: 1; + pointer-events: none; +} + +.pack-switch > span input[type="checkbox"]:hover::before { + transform: scale(1.2); +} + +.pack-switch > span input[type="checkbox"]:active::before { + transform: scale(0.8); + width: 4rem; +} + +.pack-switch > span input[type="checkbox"]:checked::before { + left: 3rem; + transform: scale(1); + background-color: var(--accent-color-plus); +} + +.pack-switch > span input[type="checkbox"]:checked:hover::before { + transform: scale(1.2); +} + +.pack-switch > span input[type="checkbox"]:checked:active::before { + left: 0.5rem; + transform: scale(0.8); + width: 4rem; +} \ No newline at end of file diff --git a/style/things/tablists.css b/style/things/tablists.css new file mode 100644 index 0000000..e69de29 diff --git a/style/things/theme.css b/style/things/theme.css new file mode 100644 index 0000000..3690514 --- /dev/null +++ b/style/things/theme.css @@ -0,0 +1,61 @@ +:root { + --accent-color: #0061e0; + --accent-color-plus: rgba(255, 255, 255, 0.75); + --accent-color-hover: rgba(255, 255, 255, 0.05); + --accent-color-active: rgba(255, 255, 255, 0.1); + + --background: #f0f6ff; + --background-plus: #fff; + --background-minus: #e0edff; + + --acrylic-background: rgba(224, 237, 255, 0.5); + --acrylic-background-plus: rgba(255, 255, 255, 0.75); + + --text-color: #333; + + --item-plus: rgba(0, 0, 0, 0.05); + --item-hover: rgba(0, 0, 0, 0.05); + --item-hover-plus: rgba(0, 0, 0, 0.1); + --item-active: rgba(0, 0, 0, 0.1); + --item-active-plus: rgba(0, 0, 0, 0.15); + + --headerbar-r: 224; + --headerbar-g: 237; + --headerbar-b: 255; + + --switch-normal: #d0e3ff; + --switch-hover: #c0d9ff; + --switch-active: #b0d0ff; +} + +@media screen and (prefers-color-scheme: dark) { + :root { + --accent-color: #80c2ff; + --accent-color-plus: rgba(0, 0, 0, 0.75); + --accent-color-hover: rgba(0, 0, 0, 0.05); + --accent-color-active: rgba(0, 0, 0, 0.1); + + --background: #000; + --background-plus: #212326; + --background-minus: #101215; + + --acrylic-background: rgba(16, 18, 21, 0.5); + --acrylic-background-plus: rgba(33, 35, 38, 0.75); + + --text-color: #e7e7e7; + + --item-plus: rgba(255, 255, 255, 0.05); + --item-hover: rgba(255, 255, 255, 0.05); + --item-hover-plus: rgba(255, 255, 255, 0.1); + --item-active: rgba(255, 255, 255, 0.1); + --item-active-plus: rgba(255, 255, 255, 0.15); + + --headerbar-r: 16; + --headerbar-g: 18; + --headerbar-b: 21; + + --switch-normal: #101215; + --switch-hover: #303235; + --switch-active: #404245; + } +} diff --git a/style/things/webview.css b/style/things/webview.css new file mode 100644 index 0000000..b81fc92 --- /dev/null +++ b/style/things/webview.css @@ -0,0 +1,17 @@ +*, ::placeholder { + font-family: system-ui; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-thumb { + background-color: #858585; + background-clip: content-box; + border: 2px solid transparent; + border-radius: 8px; + width: 8px; + height: 8px; +} diff --git a/style/utility_tray.css b/style/utility_tray.css new file mode 100644 index 0000000..e75aef8 --- /dev/null +++ b/style/utility_tray.css @@ -0,0 +1,135 @@ +#utility-tray { + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 1024; +} + +#utility-tray-motion { + background-color: var(--acrylic-background); + backdrop-filter: blur(50px) saturate(180%); + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow-x: auto; + pointer-events: all; + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; +} + +#utility-tray-motion.visible { + opacity: 1; + visibility: visible; +} + +#utility-tray-motion::-webkit-scrollbar { + display: none; +} + +.utility-tray-header { + width: 100%; + height: 5rem; + display: flex; + padding: 0 1.5rem; + box-sizing: border-box; + transition: all 0.5s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#utility-tray-motion.fade-out .utility-tray-header { + opacity: 0; + transform: scale(0.9); + visibility: hidden; +} + +.utility-tray-header h1 { + width: 100%; + flex-grow: 1; + height: 5rem; + line-height: 5rem; + margin: 0; + font-size: 2rem; + font-weight: normal; + color: var(--text-color); + padding: 0 1rem; + box-sizing: border-box; +} + +.utility-tray-header menu[role="toolbar"] { + height: 5rem; + display: flex; + padding: 0.5rem 0; + box-sizing: border-box; + margin: 0; + flex-shrink: 0; +} + +.utility-tray-header menu[role="toolbar"] > a { + width: 4rem; + height: 4rem; + line-height: 4rem; + padding: 0 1rem; + box-sizing: border-box; + margin: 0; + color: var(--text-color); + text-decoration: none; + display: inline-block; + border-radius: 2rem; +} + +.utility-tray-header menu[role="toolbar"] > a:hover { + background-color: var(--item-hover); +} + +.utility-tray-header menu[role="toolbar"] > a:active { + background-color: var(--item-active); +} + +.utility-tray-header menu[role="toolbar"] > a[data-icon]::before { + font-size: 2rem; +} + +#control-center { + position: absolute; + left: 0; + top: var(--statusbar-height); + width: 100%; + height: calc(100% - var(--statusbar-height)); + padding: 0 calc(50vw - 30rem); + box-sizing: border-box; +} + +.control-center-row { + width: 100%; + padding: 0 1.5rem; + box-sizing: border-box; + margin: 0 0 1rem; + display: flex; + gap: 1rem; + transition: all 0.5s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#utility-tray-motion .control-center-row > * { + transition: all 0.5s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#utility-tray-motion.fade-out .control-center-row > * { + opacity: 0; + transform: scale(0.9); + visibility: hidden; +} + +#notifications { + position: absolute; + left: 100%; + top: var(--statusbar-height); + width: 100%; + height: calc(100% - var(--statusbar-height)); + padding: 0 calc(50vw - 30rem); + box-sizing: border-box; +} diff --git a/style/windows.css b/style/windows.css new file mode 100644 index 0000000..d3c69d6 --- /dev/null +++ b/style/windows.css @@ -0,0 +1,112 @@ +#windows { + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; +} + +#screen.keyboard-visible #windows { + height: 60%; +} + +.appframe { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #000; + transform: translateY(100%); + visibility: hidden; +} + +.appframe.active { + transform: translateY(0); + visibility: visible; +} + +#homescreen.appframe { + transform: scale(1.5); + visibility: visible; + transition: transform 0.5s cubic-bezier(0.2, 0.9, 0.1, 1); +} + +#homescreen.appframe.active { + transform: scale(1); +} + +.appframe.expand { + border-radius: var(--screen-radius); + animation: expand 0.5s cubic-bezier(0.2, 0.9, 0.1, 1) forwards; +} + +@keyframes expand { + from { + transform: scale(0.75); + opacity: 0; + } + to { + transform: scale(1); + opacity: 1; + } +} + +.appframe.shrink { + border-radius: var(--screen-radius); + animation: shrink 0.3s cubic-bezier(0.8, 0.1, 0.9, 0) forwards; +} + +@keyframes shrink { + from { + transform: scale(1); + opacity: 1; + } + to { + transform: scale(0.75); + opacity: 0; + } +} + +.appframe.transparent { + background-color: transparent; +} + +.appframe .chrome .browser { + position: absolute; + left: 0; + top: var(--statusbar-height); + width: 100%; + height: calc(100% - var(--statusbar-height) - 2.5rem); +} + +.appframe .chrome.visible .browser { + top: calc(var(--statusbar-height) + var(--chrome-tablist-height) + var(--chrome-navbar-height) + (var(--chrome-toolbar-gap) * 2)); + height: calc(100% - var(--statusbar-height) - var(--chrome-tablist-height) - var(--chrome-navbar-height) - (var(--chrome-toolbar-gap) * 2)); +} + +#screen.software-buttons-enabled .appframe .chrome .browser { + height: calc(100% - var(--statusbar-height) - var(--software-buttons-height)); +} + +#screen.software-buttons-enabled .appframe .chrome.visible .browser { + top: calc(var(--statusbar-height) + var(--chrome-tablist-height) + var(--chrome-navbar-height) + (var(--chrome-toolbar-gap) * 2)); + height: calc(100% - var(--statusbar-height) - var(--software-buttons-height) - var(--chrome-tablist-height) - var(--chrome-navbar-height) - (var(--chrome-toolbar-gap) * 2)); +} + +.appframe.overlay .chrome .browser { + top: 0; + height: calc(100% - 2.5rem); +} + +#screen.software-buttons-enabled .appframe.overlay .chrome .browser { + height: calc(100% - var(--software-buttons-height)); +} + +.appframe.immersive .chrome .browser, +.appframe.fullscreen .chrome .browser, +#screen.software-buttons-enabled .appframe.immersive .chrome .browser, +#screen.software-buttons-enabled .appframe.fullscreen .chrome .browser { + top: 0; + height: 100%; +} diff --git a/things/buttons.css b/things/buttons.css new file mode 100644 index 0000000..e03126b --- /dev/null +++ b/things/buttons.css @@ -0,0 +1,34 @@ +.ripple-button { + position: relative; + overflow: hidden; + display: inline-block; + cursor: pointer; +} + +.ripple { + content: ""; + display: block; + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + background: radial-gradient(circle at 50% 50%, rgba(0, 0, 0, 0.2), transparent 75%); + border-radius: 50%; + pointer-events: none; +} + +.ripple.animate { + animation: rippleEffect 0.75s ease forwards; +} + +@keyframes rippleEffect { + 0% { + opacity: 1; + transform: scale(0); + } + 100% { + opacity: 0; + transform: scale(1); + } +} diff --git a/things/fonts.css b/things/fonts.css new file mode 100644 index 0000000..5f61b22 --- /dev/null +++ b/things/fonts.css @@ -0,0 +1,51 @@ +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-ExtraLight.ttf); + font-weight: 200; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Light.ttf); + font-weight: 300; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Regular.ttf); + font-weight: 400; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Medium.ttf); + font-weight: 500; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-SemiBold.ttf); + font-weight: 600; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Bold.ttf); + font-weight: 700; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-ExtraBold.ttf); + font-weight: 800; +} + +@font-face { + font-family: 'Jali Arabic'; + src: url(http://shared.localhost:8081/fonts/JaliArabic-Black.ttf); + font-weight: 900; +} + +*, ::placeholder { + font-family: 'Jali Arabic'; +} diff --git a/things/headerbars.css b/things/headerbars.css new file mode 100644 index 0000000..9c2710c --- /dev/null +++ b/things/headerbars.css @@ -0,0 +1,79 @@ +.headerbar { + width: 100%; + height: calc(var(--statusbar-height) + 5rem + (4rem * (1 - var(--progress, 0)))); + background-color: rgba(var(--headerbar-r), var(--headerbar-g), var(--headerbar-b), calc(var(--progress, 0) * 0.75)); + display: flex; + padding: var(--statusbar-height) 1rem 0; + box-sizing: border-box; + z-index: 10; + flex-shrink: 0; + backdrop-filter: blur(20px) saturate(calc(100% + (80% * var(--progress, 0)))); +} + +.headerbar .safezone { + width: 100%; + max-width: 74.5rem; + margin: 0 auto; + display: flex; +} + +.headerbar h1 { + flex-grow: 1; + margin: 0; + padding: 0 1rem; + box-sizing: border-box; + height: calc(5rem - (1rem * (1 - var(--progress, 0)))); + line-height: calc(5rem - (1rem * (1 - var(--progress, 0)))); + display: inline-block; + color: var(--text-color); + font-weight: normal; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + transform: translateY(calc(4.5rem * (1 - var(--progress, 0)))); + width: 100%; + font-size: calc(2rem + (0.8rem * (1 - var(--progress, 0)))); +} + +.headerbar a + h1 { + transform: translate(calc(-4rem * (1 - var(--progress, 0))), calc(4.5rem * (1 - var(--progress, 0)))); +} + +.headerbar a { + width: 4rem; + height: 4rem; + text-decoration: none; + line-height: 4rem; + border-radius: 50%; + display: inline-block; + color: var(--text-color); + flex-shrink: 0; + margin: 0.5rem 0; + text-align: center; + padding: 0 1rem; + box-sizing: border-box; +} + +.headerbar a:hover { + background-color: var(--item-hover); +} + +.headerbar a:active { + background-color: var(--item-active); +} + +.headerbar a[data-icon]::before { + width: 2rem; + height: 4rem; + line-height: 4rem; + font-size: 2rem; +} + +.headerbar menu[role="toolbar"] { + display: inline-flex; + height: 5rem; + flex-shrink: 0; + margin: 0; + padding: 0; + /* transform: translate(0, calc(50% * (1 - var(--progress, 0)))); */ +} diff --git a/things/icons/fonts/openorchid-icons.eot b/things/icons/fonts/openorchid-icons.eot new file mode 100644 index 0000000..92675a1 Binary files /dev/null and b/things/icons/fonts/openorchid-icons.eot differ diff --git a/things/icons/fonts/openorchid-icons.svg b/things/icons/fonts/openorchid-icons.svg new file mode 100644 index 0000000..5a9e7a0 --- /dev/null +++ b/things/icons/fonts/openorchid-icons.svg @@ -0,0 +1,959 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/things/icons/fonts/openorchid-icons.ttf b/things/icons/fonts/openorchid-icons.ttf new file mode 100644 index 0000000..666be18 Binary files /dev/null and b/things/icons/fonts/openorchid-icons.ttf differ diff --git a/things/icons/fonts/openorchid-icons.woff b/things/icons/fonts/openorchid-icons.woff new file mode 100644 index 0000000..c516071 Binary files /dev/null and b/things/icons/fonts/openorchid-icons.woff differ diff --git a/things/icons/icons.css b/things/icons/icons.css new file mode 100644 index 0000000..a369788 --- /dev/null +++ b/things/icons/icons.css @@ -0,0 +1,1454 @@ +/* Generated by grunt-webfont */ +/* Based on https://github.com/endtwist/fontcustom/blob/master/lib/fontcustom/templates/fontcustom.css */ + + +@font-face { + font-family: "openorchid-icons"; + src: url('fonts/openorchid-icons.eot'); + src: url('fonts/openorchid-icons.eot') format('embedded-opentype'), + url('fonts/openorchid-icons.ttf') format('truetype'), + url('fonts/openorchid-icons.woff') format('woff'), + url('fonts/openorchid-icons.svg#openorchid-icons') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + + +[data-icon]:before, +.ligature-icons { + font-family: "openorchid-icons"; + content: attr(data-icon); + display: inline-block; + font-weight: 500; + font-style: normal; + text-decoration: inherit; + text-transform: none; + text-rendering: optimizeLegibility; + font-size: 30px; + -webkit-font-smoothing: antialiased; +} + + +.icon-accessibility:before { + content: "\e900"; +} +.icon-achievement:before { + content: "\e901"; +} +.icon-activecall-bluetooth:before { + content: "\e902"; +} +.icon-activecall-hangup:before { + content: "\e903"; +} +.icon-activecall-hold:before { + content: "\e904"; +} +.icon-activecall-mergecalls:before { + content: "\e905"; +} +.icon-activecall-mute:before { + content: "\e906"; +} +.icon-activecall-pickup:before { + content: "\e907"; +} +.icon-activecall-sms:before { + content: "\e908"; +} +.icon-activecall-speaker:before { + content: "\e909"; +} +.icon-activecall-switchlines:before { + content: "\e90a"; +} +.icon-activecall-voicemail:before { + content: "\e90b"; +} +.icon-add:before { + content: "\e90c"; +} +.icon-addons:before { + content: "\e90d"; +} +.icon-airplane:before { + content: "\e90e"; +} +.icon-alarm-clock:before { + content: "\e90f"; +} +.icon-alarmstop:before { + content: "\e910"; +} +.icon-album:before { + content: "\e911"; +} +.icon-all-day:before { + content: "\e912"; +} +.icon-apps:before { + content: "\e913"; +} +.icon-artist:before { + content: "\e914"; +} +.icon-attachments:before { + content: "\e915"; +} +.icon-audio:before { + content: "\e916"; +} +.icon-auth:before { + content: "\e917"; +} +.icon-auto-enhance-spark:before { + content: "\e918"; +} +.icon-back:before { + content: "\e91a"; +} +.icon-back-light:before { + content: "\e91b"; +} +.icon-battery:before { + content: "\e91c"; +} +.icon-battery-0:before { + content: "\e91d"; +} +.icon-battery-10:before { + content: "\e91e"; +} +.icon-battery-100:before { + content: "\e927"; +} +.icon-battery-20:before { + content: "\e91f"; +} +.icon-battery-30:before { + content: "\e920"; +} +.icon-battery-40:before { + content: "\e921"; +} +.icon-battery-50:before { + content: "\e922"; +} +.icon-battery-60:before { + content: "\e923"; +} +.icon-battery-70:before { + content: "\e924"; +} +.icon-battery-80:before { + content: "\e925"; +} +.icon-battery-90:before { + content: "\e926"; +} +.icon-battery-charging:before { + content: "\e928"; +} +.icon-battery-charging-0:before { + content: "\e929"; +} +.icon-battery-charging-10:before { + content: "\e92a"; +} +.icon-battery-charging-100:before { + content: "\e933"; +} +.icon-battery-charging-20:before { + content: "\e92b"; +} +.icon-battery-charging-30:before { + content: "\e92c"; +} +.icon-battery-charging-40:before { + content: "\e92d"; +} +.icon-battery-charging-50:before { + content: "\e92e"; +} +.icon-battery-charging-60:before { + content: "\e92f"; +} +.icon-battery-charging-70:before { + content: "\e930"; +} +.icon-battery-charging-80:before { + content: "\e931"; +} +.icon-battery-charging-90:before { + content: "\e932"; +} +.icon-bell:before { + content: "\e934"; +} +.icon-bluetooth:before { + content: "\e935"; +} +.icon-bookmark:before { + content: "\e936"; +} +.icon-bookmarked:before { + content: "\e937"; +} +.icon-brightness:before { + content: "\e938"; +} +.icon-browser-back:before { + content: "\e939"; +} +.icon-browser-closecancel:before { + content: "\e93a"; +} +.icon-browser-crashedtab:before { + content: "\e93b"; +} +.icon-browser-forward:before { + content: "\e93c"; +} +.icon-browser-home:before { + content: "\e93d"; +} +.icon-browser-library:before { + content: "\e93e"; +} +.icon-browser-moretabs:before { + content: "\e93f"; +} +.icon-browser-nofavicon:before { + content: "\e940"; +} +.icon-browser-pictureinpicture:before { + content: "\e941"; +} +.icon-browser-readermode:before { + content: "\e942"; +} +.icon-browser-reload:before { + content: "\e943"; +} +.icon-browser-search:before { + content: "\e944"; +} +.icon-browser-secure:before { + content: "\e945"; +} +.icon-browser-secureunverified:before { + content: "\e946"; +} +.icon-browser-sidetabs:before { + content: "\e947"; +} +.icon-browser-tabpreviews:before { + content: "\e948"; +} +.icon-browsing:before { + content: "\e949"; +} +.icon-bug:before { + content: "\e94a"; +} +.icon-calendar-alarm:before { + content: "\e94b"; +} +.icon-calendar-allday:before { + content: "\e94c"; +} +.icon-calendar-bullet:before { + content: "\e94d"; +} +.icon-calendar-dot:before { + content: "\e94e"; +} +.icon-calendar-eventalarm:before { + content: "\e94f"; +} +.icon-calendar-today:before { + content: "\e950"; +} +.icon-call:before { + content: "\e951"; +} +.icon-call-incoming:before { + content: "\e952"; +} +.icon-call-outgoing:before { + content: "\e95c"; +} +.icon-call-ringing:before { + content: "\e95d"; +} +.icon-calllog-checkboxoff:before { + content: "\e953"; +} +.icon-calllog-checkboxon-box:before { + content: "\e954"; +} +.icon-calllog-checkboxon-checkmark:before { + content: "\e955"; +} +.icon-calllog-expand:before { + content: "\e956"; +} +.icon-calllog-incomingcall:before { + content: "\e957"; +} +.icon-calllog-incomingsms:before { + content: "\e958"; +} +.icon-calllog-missedcall:before { + content: "\e959"; +} +.icon-calllog-outgoingcall:before { + content: "\e95a"; +} +.icon-calllog-outgoingsms:before { + content: "\e95b"; +} +.icon-camera:before { + content: "\e95e"; +} +.icon-camera-cameraorientation:before { + content: "\e95f"; +} +.icon-camera-flashauto:before { + content: "\e960"; +} +.icon-camera-flashoff:before { + content: "\e961"; +} +.icon-camera-flashon:before { + content: "\e962"; +} +.icon-camera-videorecorder:before { + content: "\e963"; +} +.icon-change-wallpaper:before { + content: "\e964"; +} +.icon-checked:before { + content: "\e965"; +} +.icon-clear-all:before { + content: "\e966"; +} +.icon-clearcancel-circle:before { + content: "\e967"; +} +.icon-clearcancel-cross:before { + content: "\e968"; +} +.icon-close:before { + content: "\e969"; +} +.icon-closecancel:before { + content: "\e96a"; +} +.icon-collapse-chevron:before { + content: "\e96b"; +} +.icon-compose:before { + content: "\e96c"; +} +.icon-contact-add:before { + content: "\e96d"; +} +.icon-contact-addfavorite:before { + content: "\e96e"; +} +.icon-contact-addimage:before { + content: "\e96f"; +} +.icon-contact-checkmark:before { + content: "\e970"; +} +.icon-contact-delete-circle:before { + content: "\e971"; +} +.icon-contact-delete-minus:before { + content: "\e972"; +} +.icon-contact-detailfacebook-f:before { + content: "\e973"; +} +.icon-contact-detailfacebook-square:before { + content: "\e974"; +} +.icon-contact-email:before { + content: "\e975"; +} +.icon-contact-favorite:before { + content: "\e976"; +} +.icon-contact-favorited:before { + content: "\e977"; +} +.icon-contact-favoritedcontact:before { + content: "\e978"; +} +.icon-contact-find:before { + content: "\e979"; +} +.icon-contact-link:before { + content: "\e97a"; +} +.icon-contact-location:before { + content: "\e97b"; +} +.icon-contact-phone:before { + content: "\e97c"; +} +.icon-contact-sms:before { + content: "\e97e"; +} +.icon-contact-twitter:before { + content: "\e97f"; +} +.icon-contact-undo-roundarrow:before { + content: "\e981"; +} +.icon-contacts:before { + content: "\e97d"; +} +.icon-copy:before { + content: "\e982"; +} +.icon-costcontrol-topup:before { + content: "\e983"; +} +.icon-costcontrol-topuppay:before { + content: "\e984"; +} +.icon-costcontrol-topupwithcode:before { + content: "\e985"; +} +.icon-costcontrol-updatebalance:before { + content: "\e986"; +} +.icon-crop:before { + content: "\e987"; +} +.icon-cut:before { + content: "\e988"; +} +.icon-data:before { + content: "\e989"; +} +.icon-database:before { + content: "\e98a"; +} +.icon-delete:before { + content: "\e98b"; +} +.icon-desktop:before { + content: "\e98c"; +} +.icon-developer:before { + content: "\e98d"; +} +.icon-dialer-contacts:before { + content: "\e98e"; +} +.icon-dialer-delete:before { + content: "\e98f"; +} +.icon-dialer-dialpad:before { + content: "\e990"; +} +.icon-dialer-recentcalls:before { + content: "\e991"; +} +.icon-dialpad:before { + content: "\e992"; +} +.icon-discord:before { + content: "\e993"; +} +.icon-dislike:before { + content: "\e994"; +} +.icon-disliked:before { + content: "\e995"; +} +.icon-dismisskeyboard:before { + content: "\e996"; +} +.icon-display:before { + content: "\e997"; +} +.icon-do-not-track:before { + content: "\e998"; +} +.icon-download:before { + content: "\e999"; +} +.icon-download-circle:before { + content: "\e99a"; +} +.icon-edit:before { + content: "\e99b"; +} +.icon-edit-image:before { + content: "\e99d"; +} +.icon-editcontact:before { + content: "\e99c"; +} +.icon-eject:before { + content: "\e99e"; +} +.icon-email:before { + content: "\e99f"; +} +.icon-email-addrecipient-circle:before { + content: "\e9a0"; +} +.icon-email-addrecipient-plus:before { + content: "\e9a1"; +} +.icon-email-attachment:before { + content: "\e9a2"; +} +.icon-email-downloadattachment:before { + content: "\e9a3"; +} +.icon-email-flag:before { + content: "\e9a4"; +} +.icon-email-forward:before { + content: "\e9a5"; +} +.icon-email-markread:before { + content: "\e9a6"; +} +.icon-email-markunread:before { + content: "\e9a7"; +} +.icon-email-move:before { + content: "\e9a8"; +} +.icon-email-removeattachment-circle:before { + content: "\e9a9"; +} +.icon-email-removeattachment-cross:before { + content: "\e9aa"; +} +.icon-email-reply:before { + content: "\e9ab"; +} +.icon-email-replyall:before { + content: "\e9ac"; +} +.icon-email-send:before { + content: "\e9ad"; +} +.icon-emailsmscalilog-editlist:before { + content: "\e9ae"; +} +.icon-emojis:before { + content: "\e9af"; +} +.icon-eraser:before { + content: "\e9b0"; +} +.icon-expand:before { + content: "\e9b1"; +} +.icon-expand-chevron:before { + content: "\e9b2"; +} +.icon-export:before { + content: "\e9b3"; +} +.icon-face-recognition:before { + content: "\e9b5"; +} +.icon-face-recognition-fail:before { + content: "\e9b6"; +} +.icon-facebook:before { + content: "\e9b4"; +} +.icon-favorites:before { + content: "\e9b7"; +} +.icon-feedback:before { + content: "\e9b8"; +} +.icon-file:before { + content: "\e9b9"; +} +.icon-find:before { + content: "\e9ba"; +} +.icon-fingerprint:before { + content: "\e9bb"; +} +.icon-firefox:before { + content: "\e9bc"; +} +.icon-flag:before { + content: "\e9bd"; +} +.icon-flashlight:before { + content: "\e9be"; +} +.icon-fm-favouritedstation:before { + content: "\e9bf"; +} +.icon-fm-sound:before { + content: "\e9c0"; +} +.icon-folder:before { + content: "\e9c1"; +} +.icon-forbidden:before { + content: "\e9c2"; +} +.icon-forward:before { + content: "\e9c3"; +} +.icon-forward-light:before { + content: "\e9c4"; +} +.icon-ftu-importgmail:before { + content: "\e9c5"; +} +.icon-ftu-importoutlook:before { + content: "\e9c6"; +} +.icon-ftu-importsdcard:before { + content: "\e9c7"; +} +.icon-ftu-importsim:before { + content: "\e9c8"; +} +.icon-fullscreen:before { + content: "\e9c9"; +} +.icon-fullscreen-exit:before { + content: "\e9ca"; +} +.icon-gallery-autoenhancespark:before { + content: "\e9cb"; +} +.icon-gallery-crop:before { + content: "\e9cd"; +} +.icon-gallery-crop-photo:before { + content: "\e9d2"; +} +.icon-gallery-crop1x1-mark:before { + content: "\e9ce"; +} +.icon-gallery-crop2x3-mark:before { + content: "\e9cf"; +} +.icon-gallery-crop3x2-mark:before { + content: "\e9d0"; +} +.icon-gallery-cropfree-mark:before { + content: "\e9d1"; +} +.icon-gallery-exposure:before { + content: "\e9d3"; +} +.icon-gallery-filterscircleopacity100:before { + content: "\e9d6"; +} +.icon-gallery-filterscircleopacity35:before { + content: "\e9d4"; +} +.icon-gallery-filterscircleopacity50:before { + content: "\e9d5"; +} +.icon-gallery-rotate:before { + content: "\e9d7"; +} +.icon-game:before { + content: "\e9d8"; +} +.icon-gerneral-unlock:before { + content: "\e9d9"; +} +.icon-gesture:before { + content: "\e9da"; +} +.icon-gmail:before { + content: "\e9db"; +} +.icon-google:before { + content: "\e9dc"; +} +.icon-grid:before { + content: "\e9dd"; +} +.icon-heart:before { + content: "\e9de"; +} +.icon-help:before { + content: "\e9df"; +} +.icon-history:before { + content: "\e9e0"; +} +.icon-home:before { + content: "\e9e1"; +} +.icon-homescreen:before { + content: "\e9e2"; +} +.icon-homescreendelete-circle:before { + content: "\e9e3"; +} +.icon-homescreendelete-cross:before { + content: "\e9e4"; +} +.icon-info:before { + content: "\e9e5"; +} +.icon-instagram:before { + content: "\e9e6"; +} +.icon-iris-scanner:before { + content: "\e9e7"; +} +.icon-iris-scanner-fail:before { + content: "\e9e8"; +} +.icon-iris-scanner-success:before { + content: "\e9e9"; +} +.icon-keyboard:before { + content: "\e9ea"; +} +.icon-keyboard-circle:before { + content: "\e9eb"; +} +.icon-languages:before { + content: "\e9ec"; +} +.icon-left:before { + content: "\e9ed"; +} +.icon-left-light:before { + content: "\e9ee"; +} +.icon-library:before { + content: "\e9ef"; +} +.icon-like:before { + content: "\e9f0"; +} +.icon-liked:before { + content: "\e9f1"; +} +.icon-link:before { + content: "\e9f2"; +} +.icon-linkedin:before { + content: "\e9f3"; +} +.icon-location:before { + content: "\e9f4"; +} +.icon-lock:before { + content: "\e9f5"; +} +.icon-logout:before { + content: "\e9f6"; +} +.icon-media-camera:before { + content: "\e9f7"; +} +.icon-media-info:before { + content: "\e9f8"; +} +.icon-media-pause:before { + content: "\e9f9"; +} +.icon-media-play:before { + content: "\e9fa"; +} +.icon-media-playcircle:before { + content: "\e9fb"; +} +.icon-media-repeatinfinite:before { + content: "\e9fc"; +} +.icon-media-repeatonce:before { + content: "\e9fd"; +} +.icon-media-seekbackward:before { + content: "\e9fe"; +} +.icon-media-seekforward:before { + content: "\e9ff"; +} +.icon-media-shuffle:before { + content: "\ea00"; +} +.icon-media-skipbackward:before { + content: "\ea01"; +} +.icon-media-skipforward:before { + content: "\ea02"; +} +.icon-media-songs:before { + content: "\ea03"; +} +.icon-media-stop:before { + content: "\ea04"; +} +.icon-media-storage:before { + content: "\ea05"; +} +.icon-menu:before { + content: "\ea06"; +} +.icon-messages:before { + content: "\ea07"; +} +.icon-mic:before { + content: "\ea08"; +} +.icon-miscellaneous-editimage:before { + content: "\ea09"; +} +.icon-miscellaneous-select:before { + content: "\ea0a"; +} +.icon-miscellaneous-undo:before { + content: "\ea0b"; +} +.icon-moderator:before { + content: "\ea0c"; +} +.icon-moon:before { + content: "\ea0d"; +} +.icon-more:before { + content: "\ea0e"; +} +.icon-music-album:before { + content: "\ea0f"; +} +.icon-music-artist:before { + content: "\ea10"; +} +.icon-music-gridview:before { + content: "\ea11"; +} +.icon-music-playlist:before { + content: "\ea12"; +} +.icon-newadd:before { + content: "\ea13"; +} +.icon-nfc:before { + content: "\ea14"; +} +.icon-notification-bluetooth:before { + content: "\ea15"; +} +.icon-notification-bluetoothtransfer:before { + content: "\ea16"; +} +.icon-notification-cameramic:before { + content: "\ea17"; +} +.icon-notification-cameraon:before { + content: "\ea18"; +} +.icon-notification-circle:before { + content: "\ea19"; +} +.icon-notification-download:before { + content: "\ea1a"; +} +.icon-notification-downloadfailed-exclamation:before { + content: "\ea1b"; +} +.icon-notification-facebook:before { + content: "\ea1c"; +} +.icon-notification-importingfrommemorycard:before { + content: "\ea1d"; +} +.icon-notification-lowstorage:before { + content: "\ea1e"; +} +.icon-notification-mic:before { + content: "\ea1f"; +} +.icon-notifications:before { + content: "\ea20"; +} +.icon-options:before { + content: "\ea21"; +} +.icon-outlook:before { + content: "\ea22"; +} +.icon-paintbrush:before { + content: "\ea23"; +} +.icon-paintbucket:before { + content: "\ea24"; +} +.icon-paste:before { + content: "\ea25"; +} +.icon-pause:before { + content: "\ea26"; +} +.icon-permissions:before { + content: "\ea27"; +} +.icon-phone:before { + content: "\ea28"; +} +.icon-picture-in-picture:before { + content: "\ea29"; +} +.icon-pin:before { + content: "\ea2a"; +} +.icon-play:before { + content: "\ea2b"; +} +.icon-play-circle:before { + content: "\ea2c"; +} +.icon-playlist:before { + content: "\ea2d"; +} +.icon-power:before { + content: "\ea2e"; +} +.icon-qr:before { + content: "\ea2f"; +} +.icon-qr-scan:before { + content: "\ea30"; +} +.icon-quote:before { + content: "\ea31"; +} +.icon-reader-mode:before { + content: "\ea32"; +} +.icon-recent-calls:before { + content: "\ea33"; +} +.icon-redo:before { + content: "\ea34"; +} +.icon-reload:before { + content: "\ea35"; +} +.icon-repeat:before { + content: "\ea36"; +} +.icon-repeat-once:before { + content: "\ea37"; +} +.icon-right:before { + content: "\ea38"; +} +.icon-right-light:before { + content: "\ea39"; +} +.icon-save:before { + content: "\ea3a"; +} +.icon-sdcard:before { + content: "\ea3b"; +} +.icon-search:before { + content: "\ea3c"; +} +.icon-select:before { + content: "\ea3d"; +} +.icon-selectall:before { + content: "\ea3e"; +} +.icon-send:before { + content: "\ea3f"; +} +.icon-settings:before { + content: "\ea40"; +} +.icon-settings-aboutphone:before { + content: "\ea41"; +} +.icon-settings-accessibility:before { + content: "\ea42"; +} +.icon-settings-airplane:before { + content: "\ea43"; +} +.icon-settings-app-permissions:before { + content: "\ea44"; +} +.icon-settings-apps:before { + content: "\ea45"; +} +.icon-settings-appstorage:before { + content: "\ea46"; +} +.icon-settings-battery:before { + content: "\ea47"; +} +.icon-settings-bluetooth:before { + content: "\ea48"; +} +.icon-settings-brightness:before { + content: "\ea49"; +} +.icon-settings-brightness-lower:before { + content: "\ea4a"; +} +.icon-settings-call:before { + content: "\ea4b"; +} +.icon-settings-camera-permissions:before { + content: "\ea4c"; +} +.icon-settings-changewallpapericon:before { + content: "\ea4e"; +} +.icon-settings-contacts-permissions:before { + content: "\ea4f"; +} +.icon-settings-developer:before { + content: "\ea50"; +} +.icon-settings-deviceinfo:before { + content: "\ea51"; +} +.icon-settings-devicestorage-permissions:before { + content: "\ea52"; +} +.icon-settings-display:before { + content: "\ea53"; +} +.icon-settings-donottrack:before { + content: "\ea54"; +} +.icon-settings-download:before { + content: "\ea55"; +} +.icon-settings-email:before { + content: "\ea56"; +} +.icon-settings-facerecognition:before { + content: "\ea57"; +} +.icon-settings-feedback:before { + content: "\ea58"; +} +.icon-settings-findmydevice:before { + content: "\ea59"; +} +.icon-settings-fingerprint:before { + content: "\ea5a"; +} +.icon-settings-fmradio-permissions:before { + content: "\ea5b"; +} +.icon-settings-gesture:before { + content: "\ea5c"; +} +.icon-settings-gps:before { + content: "\ea5d"; +} +.icon-settings-gps-permissions:before { + content: "\ea5e"; +} +.icon-settings-help:before { + content: "\ea5f"; +} +.icon-settings-helpx:before { + content: "\ea60"; +} +.icon-settings-homescreen:before { + content: "\ea61"; +} +.icon-settings-irisscanner:before { + content: "\ea62"; +} +.icon-settings-languages:before { + content: "\ea63"; +} +.icon-settings-mediastorage:before { + content: "\ea64"; +} +.icon-settings-messages:before { + content: "\ea65"; +} +.icon-settings-network:before { + content: "\ea66"; +} +.icon-settings-nfc:before { + content: "\ea67"; +} +.icon-settings-notifications:before { + content: "\ea68"; +} +.icon-settings-persona:before { + content: "\ea69"; +} +.icon-settings-phonelock:before { + content: "\ea6a"; +} +.icon-settings-privacy:before { + content: "\ea6b"; +} +.icon-settings-simcardlock:before { + content: "\ea6c"; +} +.icon-settings-simtoolkit:before { + content: "\ea6d"; +} +.icon-settings-sound-max:before { + content: "\ea6e"; +} +.icon-settings-sound-min:before { + content: "\ea6f"; +} +.icon-settings-tethering:before { + content: "\ea70"; +} +.icon-settings-themes:before { + content: "\ea71"; +} +.icon-settings-time:before { + content: "\ea72"; +} +.icon-settings-usbstorage:before { + content: "\ea73"; +} +.icon-settings-wallpaper:before { + content: "\ea74"; +} +.icon-settings-wifi:before { + content: "\ea75"; +} +.icon-settings-wifi-1:before { + content: "\ea76"; +} +.icon-settings-wifi-2:before { + content: "\ea77"; +} +.icon-settings-wifi-3:before { + content: "\ea78"; +} +.icon-settings-wifi-4:before { + content: "\ea79"; +} +.icon-settings-wifi-lock:before { + content: "\ea7a"; +} +.icon-settings-wifi-lock-1:before { + content: "\ea7b"; +} +.icon-settings-wifi-lock-2:before { + content: "\ea7c"; +} +.icon-settings-wifi-lock-3:before { + content: "\ea7d"; +} +.icon-settings-wifi-lock-4:before { + content: "\ea7e"; +} +.icon-settings-wifi-permissions:before { + content: "\ea7f"; +} +.icon-share:before { + content: "\ea80"; +} +.icon-shopping-cart:before { + content: "\ea81"; +} +.icon-shuffle:before { + content: "\ea82"; +} +.icon-side-tabs:before { + content: "\ea83"; +} +.icon-signal-1:before { + content: "\ea84"; +} +.icon-signal-2:before { + content: "\ea85"; +} +.icon-signal-3:before { + content: "\ea86"; +} +.icon-signal-4:before { + content: "\ea87"; +} +.icon-signal-5:before { + content: "\ea88"; +} +.icon-sim:before { + content: "\ea89"; +} +.icon-skip-back:before { + content: "\ea8a"; +} +.icon-skip-forward:before { + content: "\ea8b"; +} +.icon-sms:before { + content: "\ea8c"; +} +.icon-snap-bottom:before { + content: "\ea8d"; +} +.icon-snap-bottom-left:before { + content: "\ea8e"; +} +.icon-snap-bottom-right:before { + content: "\ea8f"; +} +.icon-snap-left:before { + content: "\ea90"; +} +.icon-snap-right:before { + content: "\ea91"; +} +.icon-snap-top:before { + content: "\ea92"; +} +.icon-snap-top-left:before { + content: "\ea93"; +} +.icon-snap-top-right:before { + content: "\ea94"; +} +.icon-songs:before { + content: "\ea95"; +} +.icon-sound-max:before { + content: "\ea96"; +} +.icon-sound-min:before { + content: "\ea97"; +} +.icon-speaker:before { + content: "\ea98"; +} +.icon-splitscreen:before { + content: "\ea99"; +} +.icon-spotify-svgrepo-com:before { + content: "\ea9a"; +} +.icon-ssl:before { + content: "\ea9b"; +} +.icon-ssl-broken:before { + content: "\ea9c"; +} +.icon-stickers:before { + content: "\ea9d"; +} +.icon-storage:before { + content: "\ea9e"; +} +.icon-sync:before { + content: "\ea9f"; +} +.icon-tab-previews:before { + content: "\eaa1"; +} +.icon-tablet:before { + content: "\eaa0"; +} +.icon-taskswitcherappclose-circle:before { + content: "\eaa2"; +} +.icon-taskswitcherappclose-cross:before { + content: "\eaa3"; +} +.icon-television:before { + content: "\eaa4"; +} +.icon-tethering:before { + content: "\eaa5"; +} +.icon-textselection-copy:before { + content: "\eaa6"; +} +.icon-textselection-cut:before { + content: "\eaa7"; +} +.icon-textselection-paste:before { + content: "\eaa8"; +} +.icon-textselection-selectall:before { + content: "\eaa9"; +} +.icon-themes:before { + content: "\eaaa"; +} +.icon-threadnotsent-circle:before { + content: "\eaab"; +} +.icon-threadnotsent-exclamation:before { + content: "\eaac"; +} +.icon-tick:before { + content: "\eaad"; +} +.icon-tick-circle:before { + content: "\eaae"; +} +.icon-tiktok:before { + content: "\eaaf"; +} +.icon-time:before { + content: "\eab0"; +} +.icon-treadsent-check:before { + content: "\eab1"; +} +.icon-treadsent-circle:before { + content: "\eab2"; +} +.icon-tree:before { + content: "\eab3"; +} +.icon-tv:before { + content: "\eab4"; +} +.icon-twitch:before { + content: "\eab5"; +} +.icon-twitter:before { + content: "\eab6"; +} +.icon-undo:before { + content: "\eab7"; +} +.icon-upload:before { + content: "\eab8"; +} +.icon-usb:before { + content: "\eab9"; +} +.icon-user:before { + content: "\eaba"; +} +.icon-useraccoun-headers:before { + content: "\eabb"; +} +.icon-utility-airplanemode:before { + content: "\eabc"; +} +.icon-utility-arrow:before { + content: "\eabd"; +} +.icon-utility-battery:before { + content: "\eabe"; +} +.icon-utility-bluetooth:before { + content: "\eabf"; +} +.icon-utility-brightness:before { + content: "\eac0"; +} +.icon-utility-camera-lockedscreen:before { + content: "\eac1"; +} +.icon-utility-data:before { + content: "\eac2"; +} +.icon-utility-flashlight:before { + content: "\eac3"; +} +.icon-utility-maxvolume:before { + content: "\eac4"; +} +.icon-utility-mute-cease:before { + content: "\eac5"; +} +.icon-utility-mute-speaker:before { + content: "\eac6"; +} +.icon-utility-vibrate:before { + content: "\eac7"; +} +.icon-utility-volume:before { + content: "\eac8"; +} +.icon-utility-wifi:before { + content: "\eac9"; +} +.icon-vibrate:before { + content: "\eaca"; +} +.icon-video:before { + content: "\eacb"; +} +.icon-vpn:before { + content: "\eacc"; +} +.icon-wallpaper:before { + content: "\eacd"; +} +.icon-web:before { + content: "\eace"; +} +.icon-wifi:before { + content: "\eacf"; +} +.icon-wifi-1:before { + content: "\ead0"; +} +.icon-wifi-2:before { + content: "\ead1"; +} +.icon-wifi-3:before { + content: "\ead2"; +} +.icon-wifi-4:before { + content: "\ead3"; +} +.icon-windows:before { + content: "\ead4"; +} +.icon-wm-snapbottom:before { + content: "\ead5"; +} +.icon-wm-snapbottomleft:before { + content: "\ead6"; +} +.icon-wm-snapbottomright:before { + content: "\ead7"; +} +.icon-wm-snapleft:before { + content: "\ead8"; +} +.icon-wm-snapright:before { + content: "\ead9"; +} +.icon-wm-snaptop:before { + content: "\eada"; +} +.icon-wm-snaptopleft:before { + content: "\eadb"; +} +.icon-wm-snaptopright:before { + content: "\eadc"; +} +.icon-youtube:before { + content: "\eadd"; +} diff --git a/things/lists.css b/things/lists.css new file mode 100644 index 0000000..eb62410 --- /dev/null +++ b/things/lists.css @@ -0,0 +1,122 @@ +.lists header { + width: 100%; + max-width: 74.8rem; + padding: 0 2rem; + box-sizing: border-box; + height: 3rem; + line-height: 3rem; + color: #858585; + font-size: 1.6rem; + font-weight: bold; + text-transform: uppercase; + margin: 1rem auto 0; +} + +.lists ul { + margin: 0 auto 1.5rem; + padding: 0.5rem; + background-color: var(--background-plus); + border-radius: 1.5rem; + width: calc(100% - 3rem); + max-width: 71.8rem; + box-sizing: border-box; +} + +.lists ul li { + position: relative; + margin: 0; + list-style: none; + min-height: 5rem; + display: inline-flex; + flex-direction: column; + justify-content: center; + width: 100%; + padding: 0 1.5rem; + box-sizing: border-box; + border-radius: 1rem; + color: var(--text-color); +} + +.lists ul li:hover { + background-color: var(--item-hover); +} + +.lists ul li:active { + background-color: var(--item-active); +} + +.lists ul li.selected { + background-color: var(--accent-color); + color: var(--accent-color-plus); +} + +.lists ul li[data-icon] { + padding-inline-start: 4.5rem; +} + +.lists ul li[data-icon]::before { + position: absolute; + top: 50%; + margin-top: -1.2rem; + left: 1.2rem; + color: var(--text-color); + width: 2.4rem; + height: 2.4rem; + line-height: 2.4rem; + font-size: 2.4rem; +} + +.lists ul li.selected[data-icon]::before { + color: var(--accent-color-plus); +} + +.lists ul li.page::after { + content: 'forward'; + font-family: "openorchid-icons"; + font-size: 2rem; + color: #858585; + text-align: end; + line-height: 5rem; +} + +.lists ul li.page.selected::after { + color: var(--accent-color-plus); + opacity: 0.5; +} + +.lists ul li::after { + content: ''; + position: absolute; + left: 1.5rem; + top: 0; + width: calc(100% - 3rem); + height: 100%; + pointer-events: none; + border-bottom: solid 0.1rem var(--item-hover); + box-sizing: border-box; +} + +.lists ul li:hover::after, +.lists ul li:active::after, +.lists ul li:last-child::after { + border-bottom: none; +} + +.lists ul li p { + margin: 0; + height: 2.2rem; + line-height: 2.2rem; + font-size: 1.6rem; + color: var(--text-color); +} + +.lists ul li.selected p { + color: var(--accent-color-plus); +} + +.lists ul li p:not(:first-child) { + height: 1.9rem; + line-height: 1.9rem; + font-size: 1.4rem; + opacity: 0.5; +} diff --git a/things/main.css b/things/main.css new file mode 100644 index 0000000..e2c8636 --- /dev/null +++ b/things/main.css @@ -0,0 +1,15 @@ +html, body { + margin: 0; + padding: 0; + font-size: 10px; +} + +.app { + --statusbar-height: 4rem; + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: var(--background); +} diff --git a/things/panels.css b/things/panels.css new file mode 100644 index 0000000..b05a798 --- /dev/null +++ b/things/panels.css @@ -0,0 +1,100 @@ +.panel { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: var(--background); + display: flex; + flex-direction: column; + overflow: hidden; + z-index: 50; +} + +.panel > .content { + width: 100%; + height: 100%; + flex-grow: 1; + overflow-y: auto; + margin-top: calc((-5rem - var(--statusbar-height)) * var(--progress, 0)); + scrollbar-width: none; +} + +.panel > .content aside { + margin: 0 auto 1.5rem; + padding: 0; + background-color: var(--background-minus); + border-radius: 1.5rem; + width: calc(100% - 3rem); + max-width: 71.8rem; + box-sizing: border-box; +} + +.panel > .content aside header { + width: 100%; + padding: 0 2rem; + box-sizing: border-box; + height: 3rem; + line-height: 3rem; + color: #858585; + font-size: 1.6rem; + font-weight: bold; + text-transform: uppercase; + margin: 1rem 0 0; +} + +.panel > .content aside ul { + margin: 0; + padding: 0 0.5rem 0.5rem; + width: 100%; + background-color: transparent; +} + +.panel > .content aside ul li { + min-height: 3.2rem; + background-color: transparent; +} + +.panel > .content aside ul li > a { + color: var(--accent-color); + width: max-content; + line-height: 2.2rem; + font-size: 1.6rem; + text-decoration: none; + transition: box-shadow 0.2s ease; +} + +.panel > .content aside ul li > a:hover { + box-shadow: 0 0.2rem 0 var(--accent-color); +} + +.panel > .content aside ul li > a:active { + opacity: 0.5; +} + +@media screen and (min-width: 983px) { + .panel > .headerbar .safezone { + margin-inline-start: 0; + } + + .panel > .content header, + .panel > .content ul { + margin-inline-start: 1.5rem; + } + + .panel > .content aside { + position: absolute; + right: 0; + top: calc(5rem + var(--statusbar-height) + (4rem * (1 - var(--progress, 0)))); + width: 22rem; + margin: calc(1.5rem * var(--progress, 0)) 1.5rem 1.5rem; + } +} + +@media screen and (min-width: 1536px) { + .panel > .headerbar .safezone, + .panel > .content header, + .panel > .content ul { + margin-inline-start: auto; + } +} diff --git a/things/switches.css b/things/switches.css new file mode 100644 index 0000000..be56c72 --- /dev/null +++ b/things/switches.css @@ -0,0 +1,83 @@ +.pack-switch { + width: 100%; + display: inline-flex; +} + +.pack-switch > label { + width: 100%; + display: inline-flex; + flex-direction: column; + justify-content: center; + flex-grow: 1; +} + +.pack-switch > span { + flex-shrink: 0; + display: inline-flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.pack-switch > span input[type="checkbox"] { + background-color: var(--switch-normal); + width: 5rem; + height: 2.5rem; + border-radius: 2.5rem; + border: none; + position: relative; + outline: none; + appearance: none; + transition: all 0.1s ease; +} + +.pack-switch > span input[type="checkbox"]:hover { + background-color: var(--switch-hover); +} + +.pack-switch > span input[type="checkbox"]:hover { + background-color: var(--switch-active); +} + +.pack-switch > span input[type="checkbox"]:checked { + background-color: var(--accent-color); +} + +.pack-switch > span input[type="checkbox"]::before { + content: ''; + position: absolute; + left: 0.5rem; + top: 0.5rem; + width: 1.5rem; + height: 1.5rem; + background-color: var(--text-color); + border-radius: 1.5rem; + transition: all 0.3s cubic-bezier(0.2, 0, 0, 1); + z-index: 1; + pointer-events: none; +} + +.pack-switch > span input[type="checkbox"]:hover::before { + transform: scale(1.2); +} + +.pack-switch > span input[type="checkbox"]:active::before { + transform: scale(0.8); + width: 4rem; +} + +.pack-switch > span input[type="checkbox"]:checked::before { + left: 3rem; + transform: scale(1); + background-color: var(--accent-color-plus); +} + +.pack-switch > span input[type="checkbox"]:checked:hover::before { + transform: scale(1.2); +} + +.pack-switch > span input[type="checkbox"]:checked:active::before { + left: 0.5rem; + transform: scale(0.8); + width: 4rem; +} \ No newline at end of file diff --git a/things/tablists.css b/things/tablists.css new file mode 100644 index 0000000..e69de29 diff --git a/things/theme.css b/things/theme.css new file mode 100644 index 0000000..3690514 --- /dev/null +++ b/things/theme.css @@ -0,0 +1,61 @@ +:root { + --accent-color: #0061e0; + --accent-color-plus: rgba(255, 255, 255, 0.75); + --accent-color-hover: rgba(255, 255, 255, 0.05); + --accent-color-active: rgba(255, 255, 255, 0.1); + + --background: #f0f6ff; + --background-plus: #fff; + --background-minus: #e0edff; + + --acrylic-background: rgba(224, 237, 255, 0.5); + --acrylic-background-plus: rgba(255, 255, 255, 0.75); + + --text-color: #333; + + --item-plus: rgba(0, 0, 0, 0.05); + --item-hover: rgba(0, 0, 0, 0.05); + --item-hover-plus: rgba(0, 0, 0, 0.1); + --item-active: rgba(0, 0, 0, 0.1); + --item-active-plus: rgba(0, 0, 0, 0.15); + + --headerbar-r: 224; + --headerbar-g: 237; + --headerbar-b: 255; + + --switch-normal: #d0e3ff; + --switch-hover: #c0d9ff; + --switch-active: #b0d0ff; +} + +@media screen and (prefers-color-scheme: dark) { + :root { + --accent-color: #80c2ff; + --accent-color-plus: rgba(0, 0, 0, 0.75); + --accent-color-hover: rgba(0, 0, 0, 0.05); + --accent-color-active: rgba(0, 0, 0, 0.1); + + --background: #000; + --background-plus: #212326; + --background-minus: #101215; + + --acrylic-background: rgba(16, 18, 21, 0.5); + --acrylic-background-plus: rgba(33, 35, 38, 0.75); + + --text-color: #e7e7e7; + + --item-plus: rgba(255, 255, 255, 0.05); + --item-hover: rgba(255, 255, 255, 0.05); + --item-hover-plus: rgba(255, 255, 255, 0.1); + --item-active: rgba(255, 255, 255, 0.1); + --item-active-plus: rgba(255, 255, 255, 0.15); + + --headerbar-r: 16; + --headerbar-g: 18; + --headerbar-b: 21; + + --switch-normal: #101215; + --switch-hover: #303235; + --switch-active: #404245; + } +} diff --git a/things/webview.css b/things/webview.css new file mode 100644 index 0000000..b81fc92 --- /dev/null +++ b/things/webview.css @@ -0,0 +1,17 @@ +*, ::placeholder { + font-family: system-ui; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-thumb { + background-color: #858585; + background-clip: content-box; + border: 2px solid transparent; + border-radius: 8px; + width: 8px; + height: 8px; +}