mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 19:17:13 -05:00 
			
		
		
		
	Merge pull request #243 from paperless-ngx/css-variables
Custom color theming
This commit is contained in:
		
						commit
						8f1c4cd9c4
					
				@ -19,7 +19,7 @@ export class AppComponent implements OnInit, OnDestroy {
 | 
			
		||||
  constructor (private settings: SettingsService, private consumerStatusService: ConsumerStatusService, private toastService: ToastService, private router: Router) {
 | 
			
		||||
    let anyWindow = (window as any)
 | 
			
		||||
    anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.js';
 | 
			
		||||
    this.settings.updateDarkModeSettings()
 | 
			
		||||
    this.settings.updateAppearanceSettings()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy(): void {
 | 
			
		||||
 | 
			
		||||
@ -92,7 +92,7 @@
 | 
			
		||||
              <svg class="sidebaricon" fill="currentColor">
 | 
			
		||||
                <use xlink:href="assets/bootstrap-icons.svg#file-text"/>
 | 
			
		||||
              </svg> {{d.title | documentTitle}}
 | 
			
		||||
              <span class="close bg-light" (click)="closeDocument(d); $event.preventDefault()">
 | 
			
		||||
              <span class="close" (click)="closeDocument(d); $event.preventDefault()">
 | 
			
		||||
                <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16">
 | 
			
		||||
                  <use xlink:href="assets/bootstrap-icons.svg#x"/>
 | 
			
		||||
                </svg>
 | 
			
		||||
@ -169,7 +169,7 @@
 | 
			
		||||
          </li>
 | 
			
		||||
          <li class="nav-item">
 | 
			
		||||
            <div class="d-flex w-100 flex-wrap">
 | 
			
		||||
              <a class="nav-link pe-0 pb-0" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx">
 | 
			
		||||
              <a class="nav-link pe-2 pb-1" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx">
 | 
			
		||||
                <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="sidebaricon bi bi-github" viewBox="0 0 16 16">
 | 
			
		||||
                  <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
 | 
			
		||||
                </svg> <ng-container i18n>GitHub</ng-container>
 | 
			
		||||
 | 
			
		||||
@ -35,16 +35,14 @@
 | 
			
		||||
 | 
			
		||||
.sidebar .nav-link {
 | 
			
		||||
  font-weight: 500;
 | 
			
		||||
  color: #333;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.sidebar .nav-link .sidebaricon {
 | 
			
		||||
  margin-right: 4px;
 | 
			
		||||
  color: #999;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.sidebar .nav-link.active {
 | 
			
		||||
  color: $primary;
 | 
			
		||||
  color: var(--bs-primary);
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -172,8 +170,7 @@
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:focus {
 | 
			
		||||
      background-color: #fff;
 | 
			
		||||
      color: #212529;
 | 
			
		||||
      background-color: rgba(0, 0, 0, 0.3);
 | 
			
		||||
      flex-grow: 1;
 | 
			
		||||
      padding-left: 0.5rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@
 | 
			
		||||
      <p *ngIf="message">{{message}}</p>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="modal-footer">
 | 
			
		||||
      <button type="button" class="btn btn-outline-dark" (click)="cancel()" [disabled]="!buttonsEnabled" i18n>Cancel</button>
 | 
			
		||||
      <button type="button" class="btn btn-outline-secondary" (click)="cancel()" [disabled]="!buttonsEnabled" i18n>Cancel</button>
 | 
			
		||||
      <button type="button" class="btn" [class]="btnClass" (click)="confirm()" [disabled]="!confirmButtonEnabled || !buttonsEnabled">
 | 
			
		||||
        {{btnCaption}}
 | 
			
		||||
        <span *ngIf="!confirmButtonEnabled"> ({{seconds}})</span>
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,7 @@
 | 
			
		||||
  filter: brightness(0.5);
 | 
			
		||||
 | 
			
		||||
  &.active {
 | 
			
		||||
    background-color: lighten($primary, 30%);
 | 
			
		||||
    background-color: var(--ngx-primary-lighten-30);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
<div class="mb-3">
 | 
			
		||||
  <label [for]="inputId">{{title}}</label>
 | 
			
		||||
  <label *ngIf="title" [for]="inputId">{{title}}</label>
 | 
			
		||||
 | 
			
		||||
  <div class="input-group" [class.is-invalid]="error">
 | 
			
		||||
    <span class="input-group-text" [style.background-color]="value">   </span>
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
<app-widget-frame [title]="savedView.name">
 | 
			
		||||
 | 
			
		||||
  <a header-buttons [routerLink]="[]" (click)="showAll()" i18n>Show all</a>
 | 
			
		||||
  <a class="btn-link" header-buttons [routerLink]="[]" (click)="showAll()" i18n>Show all</a>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  <table content class="table table-sm bg-light table-hover table-borderless mb-0">
 | 
			
		||||
  <table content class="table table-sm table-hover table-borderless mb-0">
 | 
			
		||||
    <thead>
 | 
			
		||||
      <tr>
 | 
			
		||||
        <th i18n>Created</th>
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="card-body text-dark">
 | 
			
		||||
  <div class="card-body text-dark bg-light">
 | 
			
		||||
    <ng-content select ="[content]"></ng-content>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@
 | 
			
		||||
        <div class="d-flex justify-content-between align-items-center">
 | 
			
		||||
          <h5 class="card-title">
 | 
			
		||||
            <ng-container *ngIf="document.correspondent">
 | 
			
		||||
              <a *ngIf="clickCorrespondent.observers.length ; else nolink" [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold">{{(document.correspondent$ | async)?.name}}</a>
 | 
			
		||||
              <a *ngIf="clickCorrespondent.observers.length ; else nolink" [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold btn-link">{{(document.correspondent$ | async)?.name}}</a>
 | 
			
		||||
              <ng-template #nolink>{{(document.correspondent$ | async)?.name}}</ng-template>:
 | 
			
		||||
            </ng-container>
 | 
			
		||||
            {{document.title | documentTitle}}
 | 
			
		||||
 | 
			
		||||
@ -52,7 +52,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.card-selected {
 | 
			
		||||
  border-color: $primary;
 | 
			
		||||
  border-color: var(--bs-primary);
 | 
			
		||||
 | 
			
		||||
  .document-card-check {
 | 
			
		||||
    display: block;
 | 
			
		||||
@ -60,7 +60,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.doc-img-background-selected {
 | 
			
		||||
  background-color: $primaryFaded;
 | 
			
		||||
  background-color: var(--ngx-primary-faded);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.card-info {
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@
 | 
			
		||||
    <div class="card-body p-2">
 | 
			
		||||
      <p class="card-text">
 | 
			
		||||
        <ng-container *ngIf="document.correspondent">
 | 
			
		||||
          <a [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold">{{(document.correspondent$ | async)?.name}}</a>:
 | 
			
		||||
          <a [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold btn-link">{{(document.correspondent$ | async)?.name}}</a>:
 | 
			
		||||
        </ng-container>
 | 
			
		||||
        {{document.title | documentTitle}}
 | 
			
		||||
      </p>
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.card-selected {
 | 
			
		||||
  border-color: $primary;
 | 
			
		||||
  border-color:var(--bs-primary);
 | 
			
		||||
 | 
			
		||||
  .document-card-check {
 | 
			
		||||
    display: block;
 | 
			
		||||
@ -45,7 +45,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.doc-img-background-selected {
 | 
			
		||||
  background-color: $primaryFaded;
 | 
			
		||||
  background-color: var(--ngx-primary-faded);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.card-info {
 | 
			
		||||
@ -57,7 +57,7 @@
 | 
			
		||||
    &:hover,
 | 
			
		||||
    &:focus {
 | 
			
		||||
      background-color: transparent !important;
 | 
			
		||||
      color: $primary;
 | 
			
		||||
      color: var(--bs-primary);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ tr {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.table-row-selected {
 | 
			
		||||
  background-color: $primaryFaded;
 | 
			
		||||
  background-color: var(--ngx-primary-faded);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$paperless-card-breakpoints: (
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
    <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive" novalidate></app-input-check>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="modal-footer">
 | 
			
		||||
    <button type="button" class="btn btn-outline-dark" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
 | 
			
		||||
    <button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
 | 
			
		||||
    <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
 | 
			
		||||
  </div>
 | 
			
		||||
</form>
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="modal-footer">
 | 
			
		||||
      <button type="button" class="btn btn-outline-dark" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
 | 
			
		||||
      <button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
 | 
			
		||||
      <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
 | 
			
		||||
    </div>
 | 
			
		||||
  </form>
 | 
			
		||||
 | 
			
		||||
@ -100,6 +100,22 @@
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="row mb-3">
 | 
			
		||||
          <div class="col-md-3 col-form-label">
 | 
			
		||||
            <span i18n>Theme Color</span>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="col-3">
 | 
			
		||||
            <app-input-color i18n-title formControlName="themeColor" [error]="error?.color"></app-input-color>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="col-2">
 | 
			
		||||
            <button class="btn btn-link btn-sm pt-2 ps-0" [disabled]="!this.settingsForm.get('themeColor').value" (click)="clearThemeColor()">
 | 
			
		||||
              <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x me-1" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
                <path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
 | 
			
		||||
              </svg><ng-container i18n>Reset</ng-container>
 | 
			
		||||
            </button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <h4 class="mt-4" i18n>Bulk editing</h4>
 | 
			
		||||
 | 
			
		||||
        <div class="row mb-3">
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
 | 
			
		||||
    'darkModeUseSystem': new FormControl(null),
 | 
			
		||||
    'darkModeEnabled': new FormControl(null),
 | 
			
		||||
    'darkModeInvertThumbs': new FormControl(null),
 | 
			
		||||
    'themeColor': new FormControl(null),
 | 
			
		||||
    'useNativePdfViewer': new FormControl(null),
 | 
			
		||||
    'savedViews': this.savedViewGroup,
 | 
			
		||||
    'displayLanguage': new FormControl(null),
 | 
			
		||||
@ -40,6 +41,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
 | 
			
		||||
  store: BehaviorSubject<any>
 | 
			
		||||
  storeSub: Subscription
 | 
			
		||||
  isDirty$: Observable<boolean>
 | 
			
		||||
  isDirty: Boolean = false
 | 
			
		||||
 | 
			
		||||
  get computedDateLocale(): string {
 | 
			
		||||
    return this.settingsForm.value.dateLocale || this.settingsForm.value.displayLanguage || this.currentLocale
 | 
			
		||||
@ -63,6 +65,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
 | 
			
		||||
        'darkModeUseSystem': this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM),
 | 
			
		||||
        'darkModeEnabled': this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED),
 | 
			
		||||
        'darkModeInvertThumbs': this.settings.get(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED),
 | 
			
		||||
        'themeColor': this.settings.get(SETTINGS_KEYS.THEME_COLOR),
 | 
			
		||||
        'useNativePdfViewer': this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER),
 | 
			
		||||
        'savedViews': {},
 | 
			
		||||
        'displayLanguage': this.settings.getLanguage(),
 | 
			
		||||
@ -97,10 +100,21 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
 | 
			
		||||
 | 
			
		||||
      // Initialize dirtyCheck
 | 
			
		||||
      this.isDirty$ = dirtyCheck(this.settingsForm, this.store.asObservable())
 | 
			
		||||
 | 
			
		||||
      // Record dirty in case we need to 'undo' appearance settings if not saved on close
 | 
			
		||||
      this.isDirty$.subscribe(dirty => {
 | 
			
		||||
        this.isDirty = dirty
 | 
			
		||||
      })
 | 
			
		||||
      
 | 
			
		||||
      // "Live" visual changes prior to save
 | 
			
		||||
      this.settingsForm.valueChanges.subscribe(() => {
 | 
			
		||||
        this.settings.updateAppearanceSettings(this.settingsForm.get('darkModeUseSystem').value, this.settingsForm.get('darkModeEnabled').value, this.settingsForm.get('themeColor').value)
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    if (this.isDirty) this.settings.updateAppearanceSettings() // in case user changed appearance but didnt save
 | 
			
		||||
    this.storeSub && this.storeSub.unsubscribe();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -119,6 +133,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
 | 
			
		||||
    this.settings.set(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem)
 | 
			
		||||
    this.settings.set(SETTINGS_KEYS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString())
 | 
			
		||||
    this.settings.set(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED, (this.settingsForm.value.darkModeInvertThumbs == true).toString())
 | 
			
		||||
    this.settings.set(SETTINGS_KEYS.THEME_COLOR, (this.settingsForm.value.themeColor).toString())
 | 
			
		||||
    this.settings.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, this.settingsForm.value.useNativePdfViewer)
 | 
			
		||||
    this.settings.set(SETTINGS_KEYS.DATE_LOCALE, this.settingsForm.value.dateLocale)
 | 
			
		||||
    this.settings.set(SETTINGS_KEYS.DATE_FORMAT, this.settingsForm.value.dateFormat)
 | 
			
		||||
@ -129,7 +144,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
 | 
			
		||||
    this.settings.setLanguage(this.settingsForm.value.displayLanguage)
 | 
			
		||||
    this.store.next(this.settingsForm.value)
 | 
			
		||||
    this.documentListViewService.updatePageSize()
 | 
			
		||||
    this.settings.updateDarkModeSettings()
 | 
			
		||||
    this.settings.updateAppearanceSettings()
 | 
			
		||||
    this.toastService.showInfo($localize`Settings saved successfully.`)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -165,4 +180,8 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  clearThemeColor() {
 | 
			
		||||
    this.settingsForm.get('themeColor').patchValue('');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
      <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></app-input-check>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="modal-footer">
 | 
			
		||||
      <button type="button" class="btn btn-outline-dark" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
 | 
			
		||||
      <button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
 | 
			
		||||
      <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
 | 
			
		||||
    </div>
 | 
			
		||||
  </form>
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,8 @@
 | 
			
		||||
import { DOCUMENT } from '@angular/common';
 | 
			
		||||
import { Inject, Injectable, LOCALE_ID, Renderer2, RendererFactory2 } from '@angular/core';
 | 
			
		||||
import { Inject, Injectable, LOCALE_ID, Renderer2, RendererFactory2, RendererStyleFlags2 } from '@angular/core';
 | 
			
		||||
import { Meta } from '@angular/platform-browser';
 | 
			
		||||
import { CookieService } from 'ngx-cookie-service';
 | 
			
		||||
import { hexToHsl } from 'src/app/utils/color';
 | 
			
		||||
 | 
			
		||||
export interface PaperlessSettings {
 | 
			
		||||
  key: string
 | 
			
		||||
@ -27,6 +28,7 @@ export const SETTINGS_KEYS = {
 | 
			
		||||
  DARK_MODE_USE_SYSTEM: 'general-settings:dark-mode:use-system',
 | 
			
		||||
  DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled',
 | 
			
		||||
  DARK_MODE_THUMB_INVERTED: 'general-settings:dark-mode:thumb-inverted',
 | 
			
		||||
  THEME_COLOR: 'general-settings:theme:color',
 | 
			
		||||
  USE_NATIVE_PDF_VIEWER: 'general-settings:document-details:native-pdf-viewer',
 | 
			
		||||
  DATE_LOCALE: 'general-settings:date-display:date-locale',
 | 
			
		||||
  DATE_FORMAT: 'general-settings:date-display:date-format',
 | 
			
		||||
@ -43,6 +45,7 @@ const SETTINGS: PaperlessSettings[] = [
 | 
			
		||||
  {key: SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, type: "boolean", default: true},
 | 
			
		||||
  {key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false},
 | 
			
		||||
  {key: SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED, type: "boolean", default: true},
 | 
			
		||||
  {key: SETTINGS_KEYS.THEME_COLOR, type: "string", default: ""},
 | 
			
		||||
  {key: SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, type: "boolean", default: false},
 | 
			
		||||
  {key: SETTINGS_KEYS.DATE_LOCALE, type: "string", default: ""},
 | 
			
		||||
  {key: SETTINGS_KEYS.DATE_FORMAT, type: "string", default: "mediumDate"},
 | 
			
		||||
@ -68,12 +71,13 @@ export class SettingsService {
 | 
			
		||||
  ) {
 | 
			
		||||
    this.renderer = rendererFactory.createRenderer(null, null);
 | 
			
		||||
 | 
			
		||||
    this.updateDarkModeSettings()
 | 
			
		||||
    this.updateAppearanceSettings()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  updateDarkModeSettings(): void {
 | 
			
		||||
    let darkModeUseSystem = this.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM)
 | 
			
		||||
    let darkModeEnabled = this.get(SETTINGS_KEYS.DARK_MODE_ENABLED)
 | 
			
		||||
  public updateAppearanceSettings(darkModeUseSystem = null, darkModeEnabled = null, themeColor = null): void {
 | 
			
		||||
    darkModeUseSystem ??= this.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM)
 | 
			
		||||
    darkModeEnabled ??= this.get(SETTINGS_KEYS.DARK_MODE_ENABLED)
 | 
			
		||||
    themeColor ??= this.get(SETTINGS_KEYS.THEME_COLOR);
 | 
			
		||||
 | 
			
		||||
    if (darkModeUseSystem) {
 | 
			
		||||
      this.renderer.addClass(this.document.body, 'color-scheme-system')
 | 
			
		||||
@ -83,6 +87,14 @@ export class SettingsService {
 | 
			
		||||
      darkModeEnabled ? this.renderer.addClass(this.document.body, 'color-scheme-dark') : this.renderer.removeClass(this.document.body, 'color-scheme-dark')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (themeColor) {
 | 
			
		||||
      const hsl = hexToHsl(themeColor)
 | 
			
		||||
      this.renderer.setStyle(document.documentElement, '--pngx-primary',`${+hsl.h * 360},${hsl.s * 100}%`, RendererStyleFlags2.DashCase)
 | 
			
		||||
      this.renderer.setStyle(document.documentElement, '--pngx-primary-lightness',`${hsl.l * 100}%`, RendererStyleFlags2.DashCase)
 | 
			
		||||
    } else {
 | 
			
		||||
      this.renderer.removeStyle(document.documentElement, '--pngx-primary', RendererStyleFlags2.DashCase)
 | 
			
		||||
      this.renderer.removeStyle(document.documentElement, '--pngx-primary-lightness', RendererStyleFlags2.DashCase)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getLanguageOptions(): LanguageOption[] {
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
import { HSL } from "ngx-color"
 | 
			
		||||
 | 
			
		||||
function componentToHex(c) {
 | 
			
		||||
  var hex = Math.floor(c).toString(16)
 | 
			
		||||
@ -5,8 +6,8 @@ function componentToHex(c) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
 | 
			
		||||
 *
 | 
			
		||||
 * https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
 | 
			
		||||
 * Converts an HSL color value to RGB. Conversion formula
 | 
			
		||||
 * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
 | 
			
		||||
 * Assumes h, s, and l are contained in the set [0, 1] and
 | 
			
		||||
@ -42,6 +43,46 @@ function hslToRgb(h, s, l){
 | 
			
		||||
  return [r * 255, g * 255, b * 255]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
 | 
			
		||||
 * Converts an RGB color value to HSL. Conversion formula
 | 
			
		||||
 * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
 | 
			
		||||
 * Assumes r, g, and b are contained in the set [0, 255] and
 | 
			
		||||
 * returns h, s, and l in the set [0, 1].
 | 
			
		||||
 *
 | 
			
		||||
 * @param   Number  r       The red color value
 | 
			
		||||
 * @param   Number  g       The green color value
 | 
			
		||||
 * @param   Number  b       The blue color value
 | 
			
		||||
 * @return  Array           The HSL representation
 | 
			
		||||
 */
 | 
			
		||||
 export function rgbToHsl(r, g, b){
 | 
			
		||||
  r /= 255, g /= 255, b /= 255;
 | 
			
		||||
  var max = Math.max(r, g, b), min = Math.min(r, g, b);
 | 
			
		||||
  var h, s, l = (max + min) / 2;
 | 
			
		||||
 | 
			
		||||
  if(max == min){
 | 
			
		||||
      h = s = 0; // achromatic
 | 
			
		||||
  }else{
 | 
			
		||||
      var d = max - min;
 | 
			
		||||
      s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
 | 
			
		||||
      switch(max){
 | 
			
		||||
          case r: h = (g - b) / d + (g < b ? 6 : 0); break;
 | 
			
		||||
          case g: h = (b - r) / d + 2; break;
 | 
			
		||||
          case b: h = (r - g) / d + 4; break;
 | 
			
		||||
      }
 | 
			
		||||
      h /= 6;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return [h, s, l];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function hexToHsl(hex: string): HSL {
 | 
			
		||||
  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] }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function randomColor() {
 | 
			
		||||
  let rgb = hslToRgb(Math.random(), 0.6, Math.random() * 0.4 + 0.4)
 | 
			
		||||
  return `#${componentToHex(rgb[0])}${componentToHex(rgb[1])}${componentToHex(rgb[2])}`
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,11 @@
 | 
			
		||||
// bs options
 | 
			
		||||
$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";
 | 
			
		||||
@import "node_modules/bootstrap/scss/bootstrap";
 | 
			
		||||
@import "~@ng-select/ng-select/themes/default.theme.css";
 | 
			
		||||
 | 
			
		||||
.toolbaricon {
 | 
			
		||||
  width: 1.2em;
 | 
			
		||||
@ -113,10 +116,6 @@ body {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ngx-file-drop__drop-zone--over {
 | 
			
		||||
  background-color: $primaryFaded !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bootstrap 5 tweaks
 | 
			
		||||
a.badge {
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
@ -130,6 +129,6 @@ a.badge {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle {
 | 
			
		||||
    background-color: $paperless-green;
 | 
			
		||||
    border-color: $paperless-green;
 | 
			
		||||
    background-color: var(--bs-primary);
 | 
			
		||||
    border-color: var(--bs-primary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,294 @@
 | 
			
		||||
$paperless-green: #17541f;
 | 
			
		||||
$primary: #17541f;
 | 
			
		||||
$primaryFaded: #d1ddd2;
 | 
			
		||||
$enable-negative-margins: true;
 | 
			
		||||
:root {
 | 
			
		||||
  // base color e.g. #17541f = hsl(128, 57%, 21%)
 | 
			
		||||
  --pngx-primary: 128, 57%;
 | 
			
		||||
  --pngx-primary-lightness: 21%;
 | 
			
		||||
 | 
			
		||||
  --bs-primary: hsl(var(--pngx-primary), var(--pngx-primary-lightness));
 | 
			
		||||
  --bs-border-color: var(--bs-gray-400);
 | 
			
		||||
  --ngx-primary-faded: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 72%));
 | 
			
		||||
  --ngx-primary-lighten-10: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 10%));
 | 
			
		||||
  --ngx-primary-lighten-30: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 30%));
 | 
			
		||||
  --ngx-primary-darken-10: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 10%));
 | 
			
		||||
  --ngx-primary-darken-15: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 15%));
 | 
			
		||||
  --ngx-primary-darken-18: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%));
 | 
			
		||||
  --ngx-bg-darker: var(--bs-gray-100);
 | 
			
		||||
  --ngx-focus-alpha: 0.3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
svg.logo {
 | 
			
		||||
  .leaf {
 | 
			
		||||
    fill: var(--bs-primary) !important;
 | 
			
		||||
  }
 | 
			
		||||
  .text {
 | 
			
		||||
    fill: var(--bs-body-color) !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nav-link, .list-group-item {
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.bg-body {
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
  background-color: var(--bs-body-bg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.bg-primary {
 | 
			
		||||
  background-color: var(--bs-primary) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-primary {
 | 
			
		||||
  background-color: var(--bs-primary);
 | 
			
		||||
  border-color: var(--bs-primary);
 | 
			
		||||
 | 
			
		||||
  &:hover, &:focus {
 | 
			
		||||
    background-color: var(--ngx-primary-darken-10);
 | 
			
		||||
    border-color: var(--ngx-primary-darken-10);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &:disabled, &.disabled {
 | 
			
		||||
    background-color: var(--ngx-primary-darken-10) !important;
 | 
			
		||||
    border-color: var(--ngx-primary-darken-10) !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-outline-primary {
 | 
			
		||||
  border-color: var(--bs-primary) !important;
 | 
			
		||||
  color: var(--bs-primary) !important;
 | 
			
		||||
 | 
			
		||||
  &:hover, &:focus, &.active, &:active {
 | 
			
		||||
    background-color: var(--bs-primary) !important;
 | 
			
		||||
    color: var(--bs-light) !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-outline-secondary {
 | 
			
		||||
  color: var(--bs-secondary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nav-item .sidebaricon {
 | 
			
		||||
  color: var(--bs-secondary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn:focus,
 | 
			
		||||
.btn:active:focus,
 | 
			
		||||
.dropdown-item:focus,
 | 
			
		||||
.btn-check:focus + .btn,
 | 
			
		||||
.form-control:focus,
 | 
			
		||||
.form-check-input:focus,
 | 
			
		||||
.form-check-radio:focus,
 | 
			
		||||
.form-select:focus {
 | 
			
		||||
  box-shadow: 0 0 0 0.25rem hsla(var(--pngx-primary), var(--pngx-primary-lightness), var(--ngx-focus-alpha));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-switch .form-check-input:focus {
 | 
			
		||||
  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 {
 | 
			
		||||
  outline: none;
 | 
			
		||||
  background-color: var(--ngx-bg-darker);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a.navbar-brand:focus-visible {
 | 
			
		||||
  outline: none;
 | 
			
		||||
  color: var(--ngx-primary-darken-10);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dropdown.show {
 | 
			
		||||
  > .btn-primary {
 | 
			
		||||
    background-color: var(--bs-primary);
 | 
			
		||||
    border-color: var(--bs-primary);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  > .btn-outline-primary {
 | 
			
		||||
    color: var(--bs-body-color) !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a, a:hover, .btn-link, .btn-link:hover {
 | 
			
		||||
  color: var(--bs-primary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-control:not(.btn),
 | 
			
		||||
input,
 | 
			
		||||
select,
 | 
			
		||||
textarea,
 | 
			
		||||
.form-select:not(.is-invalid):not(:disabled),
 | 
			
		||||
.form-check-input {
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
  background-color: var(--bs-body-bg);
 | 
			
		||||
  border-color: var(--bs-border-color);
 | 
			
		||||
 | 
			
		||||
  &:focus {
 | 
			
		||||
    background-color: var(--ngx-bg-darker);
 | 
			
		||||
    color: var(--bs-body-color) !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-check-input:checked {
 | 
			
		||||
  background-color: var(--bs-primary);
 | 
			
		||||
  border-color: var(--bs-primary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-check-input:focus {
 | 
			
		||||
  border-color: var(--bs-primary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.page-link {
 | 
			
		||||
  color: var(--bs-light);
 | 
			
		||||
  background-color: var(--bs-body-bg);
 | 
			
		||||
  border-color: var(--bs-border-color) !important;
 | 
			
		||||
 | 
			
		||||
  &:hover, &:focus {
 | 
			
		||||
    background-color: var(--bs-primary) !important;
 | 
			
		||||
    color: var(--bs-light) !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.page-item.active .page-link {
 | 
			
		||||
  background-color: var(--bs-primary);
 | 
			
		||||
  border-color: var(--bs-primary) !important;
 | 
			
		||||
  color: var(--bs-light);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.page-item.disabled .page-link {
 | 
			
		||||
  background-color: var(--ngx-bg-darker);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nav-tabs {
 | 
			
		||||
  border-bottom: 1px solid var(--bs-border-color);
 | 
			
		||||
 | 
			
		||||
  .nav-link {
 | 
			
		||||
    color: var(--bs-primary);
 | 
			
		||||
 | 
			
		||||
    &.active, &:hover {
 | 
			
		||||
      border-color: var(--bs-border-color);
 | 
			
		||||
      background-color: var(--bs-body-bg);
 | 
			
		||||
      color: var(--bs-body-color);
 | 
			
		||||
      border-bottom: 1px solid transparent;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:focus {
 | 
			
		||||
      border-color: var(--bs-border-color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.active:focus, &:active {
 | 
			
		||||
      border-bottom: 1px solid transparent;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ng-select-container,
 | 
			
		||||
.ng-select.ng-select-opened > .ng-select-container,
 | 
			
		||||
.ng-dropdown-panel,
 | 
			
		||||
.ng-dropdown-panel .ng-dropdown-panel-items .ng-option {
 | 
			
		||||
  background-color: var(--bs-body-bg) !important;
 | 
			
		||||
  color: var(--bs-body-color) !important;
 | 
			
		||||
  border-color: var(--bs-border-color) !important;
 | 
			
		||||
 | 
			
		||||
  input:focus {
 | 
			
		||||
    background-color: transparent !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.input-group-text {
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
  background-color: var(--bs-body-bg);
 | 
			
		||||
  border-color: var(--bs-border-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.list-group-item {
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
  background-color: var(--bs-body-bg);
 | 
			
		||||
  border-color: var(--bs-border-color);
 | 
			
		||||
 | 
			
		||||
  &:hover, &:focus {
 | 
			
		||||
    background-color: var(--bs-body-bg);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dropdown-menu {
 | 
			
		||||
  background-color: var(--bs-body-bg);
 | 
			
		||||
 | 
			
		||||
  .dropdown-divider {
 | 
			
		||||
    border-color: var(--bs-border-color);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .dropdown-item {
 | 
			
		||||
    color: var(--bs-body-color);
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      background-color: var(--ngx-bg-darker);
 | 
			
		||||
      color: var(--bs-body-color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.active {
 | 
			
		||||
      background-color: var(--bs-primary);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table.table {
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
 | 
			
		||||
  .des,.asc {
 | 
			
		||||
    background-color: var(--bs-body-bg) !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.close {
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.modal .btn-close {
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ngx-file-drop__drop-zone--over {
 | 
			
		||||
  background-color: var(--ngx-primary-faded) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.alert-danger {
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
  background-color: var(--bs-danger);
 | 
			
		||||
  border-color: var(--bs-danger);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.alert-secondary {
 | 
			
		||||
  background-color: var(--ngx-primary-darken-18);
 | 
			
		||||
  border-color: var(--ngx-primary-darken-15);
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ngb-dp-header,
 | 
			
		||||
.ngb-dp-weekdays,
 | 
			
		||||
.ngb-dp-month {
 | 
			
		||||
  background-color: var(--bs-body-bg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popover {
 | 
			
		||||
  .popover-header,
 | 
			
		||||
  .popover-body {
 | 
			
		||||
    background-color: var(--ngx-bg-alt);
 | 
			
		||||
    border-color: var(--bs-border-color);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fix popover carat colors
 | 
			
		||||
.bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="left"] {
 | 
			
		||||
  border-left-color: var(--ngx-bg-alt);
 | 
			
		||||
}
 | 
			
		||||
.bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="right"] {
 | 
			
		||||
  border-right-color: var(--ngx-bg-alt);
 | 
			
		||||
}
 | 
			
		||||
.bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="top"] {
 | 
			
		||||
  border-top-color: var(--ngx-bg-alt);
 | 
			
		||||
}
 | 
			
		||||
.bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="bottom"] {
 | 
			
		||||
  border-bottom-color: var(--ngx-bg-alt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.bs-popover-bottom .popover-header::before,
 | 
			
		||||
.bs-popover-auto[x-placement^=bottom] .popover-header::before {
 | 
			
		||||
  border-bottom-color: var(--ngx-bg-alt);
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,14 @@
 | 
			
		||||
$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-accent: #21262d;
 | 
			
		||||
$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;
 | 
			
		||||
@ -12,141 +18,79 @@ $border-color-dark-mode: #47494f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin dark-mode {
 | 
			
		||||
  background-color: $bg-dark-mode !important;
 | 
			
		||||
  color: $text-color-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};
 | 
			
		||||
  --ngx-bg-darker: #{$bg-dark-mode-accent};
 | 
			
		||||
  --ngx-bg-alt: #{$bg-dark-mode-alt};
 | 
			
		||||
  --ngx-body-color-accent: #{$text-color-dark-mode-accent};
 | 
			
		||||
  --ngx-focus-alpha: 0.7;
 | 
			
		||||
 | 
			
		||||
  .navbar.bg-primary{
 | 
			
		||||
    --bs-primary: hsl(var(--pngx-primary),var(--pngx-primary-lightness));
 | 
			
		||||
    --bs-primary-rgb: var(--bs-primary);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  .navbar-brand {
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  svg.logo {
 | 
			
		||||
    .leaf {
 | 
			
		||||
      color: $primary-dark-mode !important;
 | 
			
		||||
    }
 | 
			
		||||
    .text {
 | 
			
		||||
      fill: $text-color-dark-mode !important;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .bg-light {
 | 
			
		||||
    background-color: $bg-light-dark-mode !important;
 | 
			
		||||
 | 
			
		||||
    a,
 | 
			
		||||
    div {
 | 
			
		||||
      color: $text-color-dark-mode;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .bg-body {
 | 
			
		||||
    background-color: $bg-dark-mode !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .text-light {
 | 
			
		||||
    color: $text-color-dark-mode !important;
 | 
			
		||||
    color: var(--bs-body-color);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  .border {
 | 
			
		||||
    border-color: $border-color-dark-mode !important;
 | 
			
		||||
    border-color: var(--bs-border-color) !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .border-end {
 | 
			
		||||
    border-right: 1px solid $border-color-dark-mode !important;
 | 
			
		||||
    border-right: 1px solid var(--bs-border-color) !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .border-start {
 | 
			
		||||
    border-left: 1px solid $border-color-dark-mode !important;
 | 
			
		||||
    border-left: 1px solid var(--bs-border-color) !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .border-bottom {
 | 
			
		||||
    border-bottom: 1px solid $border-color-dark-mode !important;
 | 
			
		||||
    border-bottom: 1px solid var(--bs-border-color) !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .nav-link {
 | 
			
		||||
    color: $text-color-dark-mode !important;
 | 
			
		||||
  .text-dark, .text-light {
 | 
			
		||||
    color: var(--bs-body-color) !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    &.active {
 | 
			
		||||
      background-color: $bg-dark-mode;
 | 
			
		||||
      color: $text-color-dark-mode;
 | 
			
		||||
      border-color: $border-color-dark-mode $border-color-dark-mode $bg-dark-mode;
 | 
			
		||||
 | 
			
		||||
      .close {
 | 
			
		||||
        background-color: inherit !important;
 | 
			
		||||
  .btn-outline-primary, .btn-primary {
 | 
			
		||||
    &:hover, &:focus, &.active, &:active {
 | 
			
		||||
      color: var(--ngx-body-color-accent) !important;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      color: $text-color-dark-mode-accent !important;
 | 
			
		||||
      border-color: $border-color-dark-mode $border-color-dark-mode $bg-dark-mode;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .page-item.active .page-link {
 | 
			
		||||
    background-color: darken($primary-dark-mode, 10%);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .nav-tabs {
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
 | 
			
		||||
    .nav-link {
 | 
			
		||||
      color: $primary-dark-mode !important;
 | 
			
		||||
 | 
			
		||||
      &.active {
 | 
			
		||||
        color: $text-color-dark-mode !important;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .dropdown-menu {
 | 
			
		||||
    background-color: $bg-light-dark-mode;
 | 
			
		||||
 | 
			
		||||
    .dropdown-divider {
 | 
			
		||||
      border-color: $border-color-dark-mode;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .dropdown-item {
 | 
			
		||||
      color: $text-color-dark-mode;
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        background-color: $bg-light-dark-mode;
 | 
			
		||||
        color: $text-color-dark-mode;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .dropdown-item.disabled {
 | 
			
		||||
      color: darken($text-color-dark-mode, 20%);
 | 
			
		||||
  .btn-outline-secondary {
 | 
			
		||||
    &:hover, &:focus, &.active, &:active {
 | 
			
		||||
      background-color: var(--ngx-bg-darker);
 | 
			
		||||
      color: var(--bs-primary);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .card {
 | 
			
		||||
    background-color: $bg-light-dark-mode;
 | 
			
		||||
    background-color: var(--bs-body-bg);
 | 
			
		||||
 | 
			
		||||
    .card-text {
 | 
			
		||||
      color: $text-color-dark-mode;
 | 
			
		||||
    .card-header {
 | 
			
		||||
      background-color: rgba(0, 0, 0, 0.12);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .text-dark {
 | 
			
		||||
    color: $text-color-dark-mode !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .modal-content, .modal-header, .modal-body, .modal-footer {
 | 
			
		||||
    background-color: $bg-light-dark-mode;
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
    background-color: var(--bs-body-bg);
 | 
			
		||||
    border-color: var(--bs-border-color);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  app-tag .badge {
 | 
			
		||||
    filter: brightness(.8);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .badge-light {
 | 
			
		||||
    background-color: darken($bg-dark-mode, 20%);
 | 
			
		||||
    color: $text-color-dark-mode-accent;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .badge.border-light {
 | 
			
		||||
    border-color: $bg-dark-mode !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .doc-img-container {
 | 
			
		||||
    border: none !important;
 | 
			
		||||
    border-top-left-radius: .25rem;
 | 
			
		||||
@ -157,8 +101,9 @@ $border-color-dark-mode: #47494f;
 | 
			
		||||
  .doc-img {
 | 
			
		||||
    mix-blend-mode: normal;
 | 
			
		||||
    border-radius: 0;
 | 
			
		||||
    border-color: $bg-dark-mode;
 | 
			
		||||
    border-color: var(--bs-border-color);
 | 
			
		||||
    filter: invert(10%);
 | 
			
		||||
 | 
			
		||||
    &.border-end {
 | 
			
		||||
      border-right: none !important;
 | 
			
		||||
    }
 | 
			
		||||
@ -172,34 +117,14 @@ $border-color-dark-mode: #47494f;
 | 
			
		||||
    mix-blend-mode: luminosity;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .toast {
 | 
			
		||||
    background-color: opacify($bg-light-dark-mode, .85);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .toast-header {
 | 
			
		||||
    background-color: opacify($bg-dark-mode, .85);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  a,
 | 
			
		||||
  .card-title a {
 | 
			
		||||
    color: $primary-dark-mode;
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      color: lighten($primary, 10%);
 | 
			
		||||
    }
 | 
			
		||||
  .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 {
 | 
			
		||||
    background-color: $bg-dark-mode;
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
 | 
			
		||||
    .des,
 | 
			
		||||
    .asc {
 | 
			
		||||
      background-color: transparent !important;
 | 
			
		||||
      color: $text-color-dark-mode;
 | 
			
		||||
      border-color: $border-color-dark-mode;
 | 
			
		||||
 | 
			
		||||
      &::after {
 | 
			
		||||
        filter: invert(0.8); /* arrow is a black inline png bkgd image (!) so use filter */
 | 
			
		||||
      }
 | 
			
		||||
@ -209,238 +134,31 @@ $border-color-dark-mode: #47494f;
 | 
			
		||||
      background-color: $bg-light-dark-mode;
 | 
			
		||||
      color: $text-color-dark-mode-accent;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .table td,
 | 
			
		||||
  .table th {
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .table-row-selected {
 | 
			
		||||
    background-color: $bg-light-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .table-striped > tbody > tr:nth-of-type(odd) > * {
 | 
			
		||||
    color: $text-color-dark-mode-accent;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .close {
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
  .close, .modal .btn-close {
 | 
			
		||||
    text-shadow: 0 1px 0 #666;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .modal .btn-close {
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
    text-shadow: 0 1px 0 #666;
 | 
			
		||||
    filter: invert(1) grayscale(100%) brightness(200%);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .btn-outline-primary {
 | 
			
		||||
    border-color: $primary-dark-mode;
 | 
			
		||||
    color: $primary-dark-mode;
 | 
			
		||||
 | 
			
		||||
    &:not(:disabled):not(.disabled).active,
 | 
			
		||||
    &:not(:disabled):not(.disabled):hover {
 | 
			
		||||
      background-color: darken($primary-dark-mode, 10%);
 | 
			
		||||
      border-color: darken($primary-dark-mode, 10%);
 | 
			
		||||
      color: $text-color-dark-mode-accent;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.disabled.active {
 | 
			
		||||
      background-color: darken($primary-dark-mode, 10%);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .btn-outline-secondary {
 | 
			
		||||
    border-color: darken($text-color-dark-mode, 30%);
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
 | 
			
		||||
    &:not(:disabled):not(.disabled):hover {
 | 
			
		||||
      background-color: $bg-dark-mode;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .btn-outline-danger {
 | 
			
		||||
    border-color: $danger-dark-mode;
 | 
			
		||||
    color: $danger-dark-mode;
 | 
			
		||||
 | 
			
		||||
    &:not(:disabled):not(.disabled):hover {
 | 
			
		||||
      background-color: darken($danger-dark-mode, 10%);
 | 
			
		||||
      border-color: darken($danger-dark-mode, 10%);
 | 
			
		||||
      color: $text-color-dark-mode-accent;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .btn-outline-dark {
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
 | 
			
		||||
    &:not(:disabled):not(.disabled):hover {
 | 
			
		||||
      color: $text-color-dark-mode-accent;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .btn-light:not(:disabled):not(.disabled) {
 | 
			
		||||
    background-color: $bg-dark-mode;
 | 
			
		||||
    color: $text-color-dark-mode-accent;
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      background-color: $text-color-dark-mode;
 | 
			
		||||
      color: $bg-dark-mode;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .btn-link:not(:disabled):not(.disabled) {
 | 
			
		||||
    color: $primary-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .btn-link:hover,
 | 
			
		||||
  .btn-outline-primary:not(:disabled):not(.disabled).active,
 | 
			
		||||
  .btn-outline-primary:not(:disabled):not(.disabled):active,
 | 
			
		||||
  .show > .btn-outline-primary.dropdown-toggle {
 | 
			
		||||
    color: $text-color-dark-mode-accent;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  button.bg-light:hover {
 | 
			
		||||
    background-color: $bg-dark-mode !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .card-footer button:hover {
 | 
			
		||||
    color: $primary-dark-mode !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .form-control:not(.is-invalid):not(.btn),
 | 
			
		||||
  input:not(.is-invalid),
 | 
			
		||||
  textarea:not(.is-invalid) {
 | 
			
		||||
    border-color: $border-color-dark-mode; /* we dont want to override controls that get highlighting for errors */
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .form-control:not(.btn),
 | 
			
		||||
  input,
 | 
			
		||||
  select,
 | 
			
		||||
  textarea {
 | 
			
		||||
    background-color: $bg-dark-mode;
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
 | 
			
		||||
    &::placeholder {
 | 
			
		||||
      color: $text-color-dark-mode;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:focus {
 | 
			
		||||
      background-color: $bg-light-dark-mode !important;
 | 
			
		||||
      color: darken($text-color-dark-mode, 10%) !important;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .form-select:not(.is-invalid):not(:disabled) {
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .ng-select-container,
 | 
			
		||||
  .ng-select.ng-select-opened > .ng-select-container,
 | 
			
		||||
  .ng-dropdown-panel,
 | 
			
		||||
  .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {
 | 
			
		||||
    background-color: $bg-dark-mode;
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
 | 
			
		||||
    input:focus {
 | 
			
		||||
      background-color: transparent !important;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .input-group-text {
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
    background-color: $bg-light-dark-mode;
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .list-group-item {
 | 
			
		||||
    color: $text-color-dark-mode;
 | 
			
		||||
    background-color: $bg-light-dark-mode;
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .page-item.disabled .page-link {
 | 
			
		||||
    background-color: $bg-dark-mode;
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .list-group-item,
 | 
			
		||||
  .page-link {
 | 
			
		||||
    background-color: $bg-light-dark-mode;
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .page-item.active .page-link {
 | 
			
		||||
    border-color: $border-color-dark-mode;
 | 
			
		||||
    color: $text-color-dark-mode-accent;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .progress {
 | 
			
		||||
    background-color: $border-color-dark-mode;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .alert-danger {
 | 
			
		||||
    color: $text-color-dark-mode-accent;
 | 
			
		||||
    background-color: darken($danger-dark-mode, 20%);
 | 
			
		||||
    border-color: darken($danger-dark-mode, 20%);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .bg-dark {
 | 
			
		||||
    background-color: $bg-light-dark-mode !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .ngx-file-drop__drop-zone--over {
 | 
			
		||||
    background-color: darken($primary-dark-mode, 35%) !important;
 | 
			
		||||
    background-color: var(--ngx-primary-darken-15) !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .alert-secondary {
 | 
			
		||||
    background-color: $bg-light-dark-mode;
 | 
			
		||||
    border-color: darken($bg-light-dark-mode, 10%);
 | 
			
		||||
    color: $text-color-dark-mode-accent;
 | 
			
		||||
  .toast {
 | 
			
		||||
    background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%), 0.9);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  .progress-bar.bg-primary {
 | 
			
		||||
    background-color: darken($primary-dark-mode, 5%) !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .popover {
 | 
			
		||||
    .popover-header,
 | 
			
		||||
    .popover-body {
 | 
			
		||||
      background-color: $bg-dark-mode-accent;
 | 
			
		||||
      border-color: $border-color-dark-mode;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // fix popover carat colors
 | 
			
		||||
  .bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="left"] {
 | 
			
		||||
    border-left-color: $bg-dark-mode-accent;
 | 
			
		||||
  }
 | 
			
		||||
  .bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="right"] {
 | 
			
		||||
    border-right-color: $bg-dark-mode-accent;
 | 
			
		||||
  }
 | 
			
		||||
  .bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="top"] {
 | 
			
		||||
    border-top-color: $bg-dark-mode-accent;
 | 
			
		||||
  }
 | 
			
		||||
  .bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="bottom"] {
 | 
			
		||||
    border-bottom-color: $bg-dark-mode-accent;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .bs-popover-bottom .popover-header::before,
 | 
			
		||||
  .bs-popover-auto[x-placement^=bottom] .popover-header::before {
 | 
			
		||||
    border-bottom-color: $bg-dark-mode-accent;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .ngb-dp-header,
 | 
			
		||||
  .ngb-dp-weekdays,
 | 
			
		||||
  .ngb-dp-month {
 | 
			
		||||
    background-color: $bg-light-dark-mode;
 | 
			
		||||
  .toast-header {
 | 
			
		||||
    background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 10%), 0.9);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user