Merge branch 'main' into dev

This commit is contained in:
Michael Shamoon
2022-04-25 10:33:40 -07:00
68 changed files with 1445 additions and 367 deletions

View File

@@ -1,4 +1,3 @@
@import "/src/theme";
/*
* Sidebar
*/
@@ -36,10 +35,15 @@
.sidebar .nav-link {
font-weight: 500;
&:hover, &.active {
&:hover, &.active, &:focus {
color: var(--bs-primary);
}
&:focus-visible {
outline: none;
background-color: var(--bs-body-bg);
}
&.active {
font-weight: bold;
}

View File

@@ -1,5 +1,3 @@
@import "/src/theme";
.badge-corner {
position: absolute;
top: -8px;

View File

@@ -1,5 +1,3 @@
@import "/src/theme";
form {
position: relative;
}

View File

@@ -1,5 +1,3 @@
@import "/src/theme";
.result-content {
overflow-wrap: anywhere;
}

View File

@@ -1,5 +1,3 @@
@import "/src/theme";
.card-text {
font-size: 90%;
}

View File

@@ -1,5 +1,3 @@
@import "/src/theme";
::ng-deep app-document-list app-page-header > div.mb-3 {
margin-bottom: 0 !important;
}

View File

@@ -7,7 +7,7 @@
<ul ngbNav #nav="ngbNav" class="nav-tabs">
<li [ngbNavItem]="1">
<a ngbNavLink i18n>General settings</a>
<a ngbNavLink i18n>General</a>
<ng-template ngbNavContent>
<h4 i18n>Appearance</h4>
@@ -104,7 +104,7 @@
<div class="col-md-3 col-form-label">
<span i18n>Theme Color</span>
</div>
<div class="col-3">
<div class="col col-md-3">
<app-input-color i18n-title formControlName="themeColor" [error]="error?.color"></app-input-color>
</div>
<div class="col-2">

View File

@@ -9,7 +9,11 @@ import {
} from '@angular/core'
import { Meta } from '@angular/platform-browser'
import { CookieService } from 'ngx-cookie-service'
import { hexToHsl } from 'src/app/utils/color'
import {
BRIGHTNESS,
estimateBrightnessForColor,
hexToHsl,
} from 'src/app/utils/color'
export interface PaperlessSettings {
key: string
@@ -132,28 +136,41 @@ export class SettingsService {
: this.renderer.removeClass(this.document.body, 'color-scheme-dark')
}
// remove these in case they were there
this.renderer.removeClass(this.document.body, 'primary-dark')
this.renderer.removeClass(this.document.body, 'primary-light')
if (themeColor) {
const hsl = hexToHsl(themeColor)
const bgBrightnessEstimate = estimateBrightnessForColor(themeColor)
if (bgBrightnessEstimate == BRIGHTNESS.DARK) {
this.renderer.addClass(this.document.body, 'primary-dark')
this.renderer.removeClass(this.document.body, 'primary-light')
} else {
this.renderer.addClass(this.document.body, 'primary-light')
this.renderer.removeClass(this.document.body, 'primary-dark')
}
this.renderer.setStyle(
document.documentElement,
document.body,
'--pngx-primary',
`${+hsl.h * 360},${hsl.s * 100}%`,
RendererStyleFlags2.DashCase
)
this.renderer.setStyle(
document.documentElement,
document.body,
'--pngx-primary-lightness',
`${hsl.l * 100}%`,
RendererStyleFlags2.DashCase
)
} else {
this.renderer.removeStyle(
document.documentElement,
document.body,
'--pngx-primary',
RendererStyleFlags2.DashCase
)
this.renderer.removeStyle(
document.documentElement,
document.body,
'--pngx-primary-lightness',
RendererStyleFlags2.DashCase
)

View File

@@ -1,4 +1,9 @@
import { HSL } from 'ngx-color'
import { HSL, RGB } from 'ngx-color'
export const BRIGHTNESS = {
LIGHT: 'light',
DARK: 'dark',
}
function componentToHex(c) {
var hex = Math.floor(c).toString(16)
@@ -86,14 +91,42 @@ export function rgbToHsl(r, g, b) {
}
export function hexToHsl(hex: string): HSL {
const rgb = hexToRGB(hex)
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b)
return { h: hsl[0], s: hsl[1], l: hsl[2] }
}
export function hexToRGB(hex: string): RGB {
hex = hex.replace('#', '')
let aRgbHex = hex.match(/.{1,2}/g)
const hsl = rgbToHsl(
parseInt(aRgbHex[0], 16),
parseInt(aRgbHex[1], 16),
parseInt(aRgbHex[2], 16)
)
return { h: hsl[0], s: hsl[1], l: hsl[2] }
return {
r: parseInt(aRgbHex[0], 16),
g: parseInt(aRgbHex[1], 16),
b: parseInt(aRgbHex[2], 16),
}
}
export function computeLuminance(color: RGB) {
// Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
const colorKeys = Object.keys(color)
for (var i = 0; i < 3; i++) {
var rgb = color[colorKeys[i]]
rgb /= 255
rgb = rgb < 0.03928 ? rgb / 12.92 : Math.pow((rgb + 0.055) / 1.055, 2.4)
color[i] = rgb
}
return 0.2126 * color[0] + 0.7152 * color[1] + 0.0722 * color[2]
}
export function estimateBrightnessForColor(colorHex: string) {
// See <https://www.w3.org/TR/WCAG20/#contrast-ratiodef>
// Adapted from https://api.flutter.dev/flutter/material/ThemeData/estimateBrightnessForColor.html
const rgb = hexToRGB(colorHex)
const luminance = computeLuminance(rgb)
const kThreshold = 0.15
return (luminance + 0.05) * (luminance + 0.05) > kThreshold
? BRIGHTNESS.LIGHT
: BRIGHTNESS.DARK
}
export function randomColor() {

View File

@@ -5,7 +5,7 @@ export const environment = {
apiBaseUrl: document.baseURI + 'api/',
apiVersion: '2',
appTitle: 'Paperless-ngx',
version: '1.6.0',
version: '1.7.0',
webSocketHost: window.location.host,
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
webSocketBaseUrl: base_url.pathname + 'ws/',

View File

@@ -616,7 +616,7 @@
<context context-type="linenumber">4</context>
</context-group>
<note priority="1" from="description">This button dismisses all status messages about processed documents on the dashboard (failed and successful)</note>
<target state="translated">Afskedig afsluttede</target>
<target state="translated">Ryd afsluttede</target>
</trans-unit>
<trans-unit id="118343233500414755" datatype="html">
<source>Drop documents here or</source>
@@ -2016,7 +2016,7 @@
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">17</context>
</context-group>
<target state="translated">Visning sprog</target>
<target state="translated">Visningssprog</target>
</trans-unit>
<trans-unit id="53523152145406584" datatype="html">
<source>You need to reload the page after applying a new language.</source>
@@ -2232,7 +2232,7 @@
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">163</context>
</context-group>
<target state="translated">Ingen gemte visninger angivet.</target>
<target state="translated">Ingen gemte visninger.</target>
</trans-unit>
<trans-unit id="5610279464668232148" datatype="html" approved="yes">
<source>Saved view &quot;<x id="PH" equiv-text="savedView.name"/>&quot; deleted.</source>

View File

@@ -2136,7 +2136,7 @@
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">103</context>
</context-group>
<target state="final">Edition en masse</target>
<target state="final">Édition en masse</target>
</trans-unit>
<trans-unit id="8158899674926420054" datatype="html" approved="yes">
<source>Show confirmation dialogs</source>

View File

@@ -2452,7 +2452,7 @@
<context context-type="sourcefile">src/app/services/open-documents.service.ts</context>
<context context-type="linenumber">97</context>
</context-group>
<target state="translated">Istnieją niezapisane zmiany.</target>
<target state="translated">Masz niezapisane zmiany.</target>
</trans-unit>
<trans-unit id="3305084982600522070" datatype="html">
<source>Are you sure you want to leave?</source>

View File

@@ -54,14 +54,14 @@
</context-group>
<target state="final">Документ <x id="PH" equiv-text="status.filename"/> обрабатывается paperless</target>
</trans-unit>
<trans-unit id="2173456130768795374" datatype="html">
<trans-unit id="2173456130768795374" datatype="html" approved="yes">
<source>Paperless-ngx</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/app-frame/app-frame.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">app title</note>
<target state="translated">Paperless-ngx</target>
<target state="final">Paperless-ngx</target>
</trans-unit>
<trans-unit id="7100953725264790651" datatype="html" approved="yes">
<source>Search documents</source>
@@ -433,7 +433,7 @@
<context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
<context context-type="linenumber">45</context>
</context-group>
<target state="translated">Нажмите снова, чтобы исключить элементы.</target>
<target state="translated">Нажмите еще раз, чтобы исключить элементы.</target>
</trans-unit>
<trans-unit id="7593728289020204896" datatype="html" approved="yes">
<source>Not assigned</source>

View File

@@ -1352,7 +1352,7 @@
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
<context context-type="linenumber">202</context>
</context-group>
<target state="translated">Ova radnja će trajno obrisati <x id="PH" equiv-text="this.list.selected.size"/> selektovane dokumente.</target>
<target state="translated">Ova radnja će trajno obrisati <x id="PH" equiv-text="this.list.selected.size"/> selektovan(a) dokument(a).</target>
</trans-unit>
<trans-unit id="5641451190833696892" datatype="html">
<source>This operation cannot be undone.</source>

View File

@@ -4,7 +4,6 @@ $enable-negative-margins: true;
@import "node_modules/bootstrap/scss/bootstrap";
@import "~@ng-select/ng-select/themes/default.theme.css";
@import "theme";
@import "theme_dark";
@import "print";
// Paperless-ngx styles
@@ -26,6 +25,27 @@ svg.logo {
}
}
.navbar.bg-primary {
--bs-primary: hsl(var(--pngx-primary),var(--pngx-primary-lightness));
--bs-primary-rgb: var(--bs-primary);
}
.border {
border-color: var(--bs-border-color) !important;
}
.border-end {
border-right: 1px solid var(--bs-border-color) !important;
}
.border-start {
border-left: 1px solid var(--bs-border-color) !important;
}
.border-bottom {
border-bottom: 1px solid var(--bs-border-color) !important;
}
.nav-link, .list-group-item {
color: var(--bs-body-color);
}
@@ -36,20 +56,31 @@ svg.logo {
.bg-primary {
background-color: var(--bs-primary) !important;
color: var(--pngx-primary-text-contrast);
}
.navbar-brand {
color: var(--pngx-primary-text-contrast) !important;
}
.navbar .dropdown .btn {
color: var(--pngx-primary-text-contrast) !important;
}
.btn-primary {
color: var(--pngx-primary-text-contrast);
background-color: var(--bs-primary);
border-color: var(--bs-primary);
&:hover, &:focus {
background-color: var(--pngx-primary-darken-10);
border-color: var(--pngx-primary-darken-10);
background-color: var(--pngx-primary-darken-5);
border-color: var(--pngx-primary-darken-5);
}
&:disabled, &.disabled {
background-color: var(--pngx-primary-darken-10) !important;
border-color: var(--pngx-primary-darken-10) !important;
color: var(--pngx-primary-text-contrast);
background-color: var(--pngx-primary-darken-5) !important;
border-color: var(--pngx-primary-darken-5) !important;
}
}
@@ -90,14 +121,14 @@ svg.logo {
background-image: escape-svg(url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#bbb'/></svg>"));
}
.nav-link:focus-visible, .nav-item a:focus-visible {
.nav-item a:focus-visible {
outline: none;
background-color: var(--pngx-bg-darker);
background-color: var(--bs-body-bg);
}
a.navbar-brand:focus-visible {
outline: none;
color: var(--pngx-primary-darken-10);
color: var(--pngx-primary-darken-5);
}
.dropdown.show {
@@ -209,7 +240,8 @@ input,
select,
textarea,
.form-select:not(.is-invalid):not(:disabled),
.form-check-input {
.form-check-input,
.ng-select .ng-select-container .ng-value-container .ng-input > input {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
@@ -324,6 +356,13 @@ textarea,
}
}
.doc-img-container {
border: none !important;
border-top-left-radius: .25rem;
border-top-right-radius: .25rem;
overflow: hidden;
}
// icons
.toolbaricon {
width: 1.2em;
@@ -403,10 +442,8 @@ table.table {
border-color: var(--bs-danger);
}
.alert-secondary {
background-color: var(--pngx-primary-darken-18);
border-color: var(--pngx-primary-darken-15);
color: var(--bs-body-color);
.progress {
background-color: var(--bs-body-bg);
}
.ngb-dp-header,

View File

@@ -1,17 +1,222 @@
:root {
@mixin paperless-green {
// base color e.g. #17541f = hsl(128, 57%, 21%)
--pngx-primary: 128, 57%;
--pngx-primary-lightness: 21%;
}
body {
@include paperless-green;
--pngx-primary-text-contrast: var(--bs-light);
--bs-primary: hsl(var(--pngx-primary), var(--pngx-primary-lightness));
--bs-border-color: var(--bs-gray-400);
--pngx-primary-faded: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 72%));
--pngx-primary-lighten-10: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 10%));
--pngx-primary-lighten-30: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 30%));
--pngx-primary-darken-10: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 10%));
--pngx-primary-darken-5: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 5%));
--pngx-primary-darken-15: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 15%));
--pngx-primary-darken-18: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%));
--pngx-bg-alt: #fff;
--pngx-bg-darker: var(--bs-gray-100);
--pngx-focus-alpha: 0.3;
}
// Dark text colors allow for maintain contrast with theme color changes
$text-color-light-bg: #212529;
$text-color-dark-bg: #abb2bf;
$text-color-dark-bg-accent: lighten($text-color-dark-bg, 10%);
// Taken from bootstrap
$form-check-input-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><path fill='none' stroke='#{$text-color-light-bg}' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/></svg>");
$form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='2' fill='#{$text-color-light-bg}'/></svg>");
.primary-light {
--pngx-primary-text-contrast: #{$text-color-light-bg} !important;
.form-check-input:checked[type=checkbox] {
background-image: escape-svg($form-check-input-checked-bg-image-dark);
}
.form-check-input:checked[type=radio] {
background-image: escape-svg($form-check-radio-checked-bg-image-dark);
}
.btn-close {
filter: none !important;
}
}
.primary-dark {
--pngx-primary-text-contrast: #{$text-color-dark-bg} !important;
}
// Dark mode
@mixin paperless-green-dark-mode {
--pngx-primary-lightness: 31%;
}
@mixin dark-mode {
--bs-body-color: #{$text-color-dark-bg};
--pngx-body-color-accent: #{$text-color-dark-bg-accent};
--bs-danger: #b71631;
--bs-danger-rgb: 183, 22, 49;
--bs-body-bg: #161618;
--bs-body-bg-rgb: 22, 22, 24;
--bs-light: #1c1c1f;
--bs-light-rgb: 28, 28, 31;
--bs-border-color: #47494f;
--pngx-bg-darker: #101216;
--pngx-bg-alt: #242529;
--pngx-focus-alpha: 0.6;
--pngx-primary-faded: var(--pngx-primary-darken-15);
--pngx-primary-text-contrast: var(--bs-body-color);
.text-dark, .text-light {
color: var(--bs-body-color) !important;
}
.btn-primary {
&:hover, &:focus, &.active, &:active {
color: var(--bs-body-color) !important;
}
}
.btn-outline-primary {
&:hover, &:focus, &.active, &:active {
color: var(--bs-light) !important;
}
}
.btn-outline-secondary {
&:hover, &:focus, &.active, &:active {
background-color: var(--pngx-bg-darker);
color: var(--bs-primary);
}
}
.btn-light {
color: var(--bs-body-color);
}
.btn .progress {
background-color: var(--pngx-body-color-accent);
}
.search-form-container {
input, input:focus {
color: var(--bs-body-color) !important;
}
}
.card {
background-color: var(--bs-body-bg);
.card-header {
background-color: rgba(0, 0, 0, 0.12);
}
}
.modal-content, .modal-header, .modal-body, .modal-footer {
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
}
app-tag .badge {
filter: brightness(.8);
}
.doc-img {
mix-blend-mode: normal;
border-radius: 0;
border-color: var(--bs-border-color);
filter: invert(10%);
&.border-end {
border-right: none !important;
}
}
.doc-img.inverted {
filter: invert(95%) hue-rotate(180deg);
}
.card-selected .doc-img {
mix-blend-mode: luminosity;
}
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option:hover,
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {
background-color: var(--bs-light);
}
table {
.des,
.asc {
&::after {
filter: invert(0.8); /* arrow is a black inline png bkgd image (!) so use filter */
}
}
&.table-hover > tbody > tr:hover > * {
background-color: var(--bs-light);
color: var(--pngx-body-color-accent);
}
}
.alert-secondary {
background-color: var(--bs-light);
border-color: var(--pngx-bg-darker);
color: var(--bs-body-color);
}
.table-striped > tbody > tr:nth-of-type(odd) > * {
color: var(--pngx-body-color-accent);
}
.close, .modal .btn-close, .alert .btn-close {
text-shadow: 0 1px 0 #666;
}
.modal .btn-close, .alert .btn-close, .toast .btn-close {
filter: invert(1) grayscale(100%) brightness(200%);
}
.toast, .toast-header {
background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 15%), 0.8);
}
.toast,
.toast .toast-header,
.toast .btn-close {
color: var(--pngx-primary-text-contrast);
}
}
body.color-scheme-dark {
// no custom theme color
&:not(.primary-light):not(.primary-dark) {
@include paperless-green-dark-mode;
.navbar.bg-primary {
// navbar is og green in dark mode
@include paperless-green;
}
}
@include dark-mode;
}
@media (prefers-color-scheme: dark) {
body.color-scheme-system {
// no custom theme color
&:not(.primary-light):not(.primary-dark) {
@include paperless-green-dark-mode;
.navbar.bg-primary {
// navbar is og green in dark mode
@include paperless-green;
}
}
@include dark-mode;
}
}

View File

@@ -1,171 +0,0 @@
$primary-dark-mode: #45973a;
$primary-dark-mode-rgb: 69, 151, 58;
$primary-dark-mode-darken-10: darken($primary-dark-mode, 10%);
$danger-dark-mode: #b71631;
$danger-dark-mode-rgb: 183, 22, 49;
$bg-dark-mode: #161618;
$bg-dark-mode-rgb: 22, 22, 24;
$bg-dark-mode-accent: #101216;
$bg-dark-mode-alt: #242529;
$bg-light-dark-mode: #1c1c1f;
$bg-light-dark-mode-rgb: 28, 28, 31;
$text-color-dark-mode: #abb2bf;
$text-color-dark-mode-accent: lighten($text-color-dark-mode, 10%);
$border-color-dark-mode: #47494f;
@mixin dark-mode {
--bs-primary: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 10%));
--bs-danger: #{$danger-dark-mode};
--bs-danger-rgb: #{$danger-dark-mode-rgb};
--bs-body-bg: #{$bg-dark-mode};
--bs-body-bg-rgb: #{$bg-dark-mode-rgb};
--bs-body-color: #{$text-color-dark-mode};
--bs-light: #{$bg-light-dark-mode};
--bs-light-rgb: #{$bg-light-dark-mode-rgb};
--bs-border-color: #{$border-color-dark-mode};
--pngx-bg-darker: #{$bg-dark-mode-accent};
--pngx-bg-alt: #{$bg-dark-mode-alt};
--pngx-body-color-accent: #{$text-color-dark-mode-accent};
--pngx-focus-alpha: 0.7;
--pngx-primary-faded: var(--pngx-primary-darken-15);
--pngx-primary-text-contrast: var(--bs-body-color);
.navbar.bg-primary{
--bs-primary: hsl(var(--pngx-primary),var(--pngx-primary-lightness));
--bs-primary-rgb: var(--bs-primary);
}
.navbar-brand {
color: var(--bs-body-color);
}
.border {
border-color: var(--bs-border-color) !important;
}
.border-end {
border-right: 1px solid var(--bs-border-color) !important;
}
.border-start {
border-left: 1px solid var(--bs-border-color) !important;
}
.border-bottom {
border-bottom: 1px solid var(--bs-border-color) !important;
}
.text-dark, .text-light {
color: var(--bs-body-color) !important;
}
.btn-outline-primary, .btn-primary {
&:hover, &:focus, &.active, &:active {
color: var(--bs-light) !important;
}
}
.btn-outline-secondary {
&:hover, &:focus, &.active, &:active {
background-color: var(--pngx-bg-darker);
color: var(--bs-primary);
}
}
.search-form-container {
input, input:focus {
color: var(--bs-body-color) !important;
}
}
.card {
background-color: var(--bs-body-bg);
.card-header {
background-color: rgba(0, 0, 0, 0.12);
}
}
.modal-content, .modal-header, .modal-body, .modal-footer {
background-color: var(--bs-body-bg);
border-color: var(--bs-border-color);
}
app-tag .badge {
filter: brightness(.8);
}
.doc-img-container {
border: none !important;
border-top-left-radius: .25rem;
border-top-right-radius: .25rem;
overflow: hidden;
}
.doc-img {
mix-blend-mode: normal;
border-radius: 0;
border-color: var(--bs-border-color);
filter: invert(10%);
&.border-end {
border-right: none !important;
}
}
.doc-img.inverted {
filter: invert(95%) hue-rotate(180deg);
}
.card-selected .doc-img {
mix-blend-mode: luminosity;
}
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option:hover,
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {
background-color: $bg-light-dark-mode;
}
table {
.des,
.asc {
&::after {
filter: invert(0.8); /* arrow is a black inline png bkgd image (!) so use filter */
}
}
&.table-hover > tbody > tr:hover > * {
background-color: $bg-light-dark-mode;
color: $text-color-dark-mode-accent;
}
}
.table-striped > tbody > tr:nth-of-type(odd) > * {
color: $text-color-dark-mode-accent;
}
.close, .modal .btn-close, .alert .btn-close {
text-shadow: 0 1px 0 #666;
}
.modal .btn-close, .alert .btn-close {
filter: invert(1) grayscale(100%) brightness(200%);
}
.toast {
background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%), 0.9);
}
.toast-header {
background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 10%), 0.9);
}
}
body.color-scheme-dark {
@include dark-mode;
}
body.color-scheme-system {
@media (prefers-color-scheme: dark) {
@include dark-mode;
}
}