Compare commits

..

20 Commits

Author SHA1 Message Date
nico.hdr8
054715688f fix(navbar): other blur config 2025-10-08 16:39:22 +02:00
nico.hdr8
cb044eb720 fix(navbar): make blur behind navigation-bar bigger 2025-10-08 16:33:56 +02:00
nico.hdr8
b1a16e6bb8 fix(core): compress images 2025-10-08 16:03:36 +02:00
nico.hdr8
0979f62718 feat(background): make stars faster 2025-10-08 09:12:29 +02:00
nico.hdr8
0b88d4e670 Merge branch 'main' of ssh://git.byhaider.dev:1103/nico/byhaider-homepage 2025-10-07 14:43:17 +02:00
nico.hdr8
e7de29542a fix(core): navigation bar moved when scrolling 2025-10-07 14:42:45 +02:00
3a3b331092 deploy(core): add dockerfile and compose (and deploy) 2025-10-07 14:37:47 +02:00
nico.hdr8
b482baf56d feat(core): add copyright 2025-10-07 14:36:25 +02:00
nico.hdr8
610328129d feat(navigation-bar): add theme- and language-buttons to mobile-menu 2025-10-07 13:59:13 +02:00
nico.hdr8
9b83c162f3 feat(about): add small impressum 2025-10-07 13:53:24 +02:00
nico.hdr8
d9d6a459ed style(home): animate section 2025-10-07 13:51:45 +02:00
nico.hdr8
0d65cdbc65 fix(background): star generation outside of view (scroll height) 2025-10-07 13:13:58 +02:00
nico.hdr8
5138bd3b58 style(navigation-bar): make navbar responsive 2025-10-07 11:56:18 +02:00
nico.hdr8
ba5b2694a3 feat(core): page in work image 2025-10-07 11:10:19 +02:00
nico.hdr8
a3acd4029b style(home): make homepage responsive 2025-10-07 10:58:10 +02:00
nico.hdr8
1b41bd32cb style(core): small changes 2025-10-06 15:17:36 +02:00
nico.hdr8
95a7fa3d9c style(core): change background color 2025-10-06 15:12:13 +02:00
nico.hdr8
1aaa54d3b5 feat(home): implement and style first section at home 2025-10-06 14:58:09 +02:00
nico.hdr8
505f505176 feat(core): new page "projects" 2025-10-06 14:57:50 +02:00
nico.hdr8
9a855f8543 feat(core): change theme color and stars count 2025-10-06 13:09:37 +02:00
24 changed files with 275 additions and 100 deletions

14
Dockerfile Normal file
View File

@@ -0,0 +1,14 @@
FROM node:latest AS build
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
RUN npm run build --production
RUN echo "Contents of /app/dist/byhaider-homepage/browser:" && ls -l /app/dist/byhaider-homepage/browser
FROM nginx:alpine
COPY --from=build /app/dist/byhaider-homepage/browser /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

19
compose.yaml Normal file
View File

@@ -0,0 +1,19 @@
services:
homepage:
build:
context: .
image: byhaider-homepage:latest
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.byhaider-homepage.rule=Host(`byhaider.dev`)"
- "traefik.http.routers.byhaider-homepage.entrypoints=websecure"
- "traefik.http.routers.byhaider-homepage.tls=true"
- "traefik.http.routers.byhaider-homepage.tls.certResolver=cloudflare"
- "traefik.http.services.byhaider-homepage.loadbalancer.server.port=80"
networks:
- traefik-network
networks:
traefik-network:
external: true

25
deploy.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
set -e
echo "🚀 Starte Deployment für byHaider-Homepage..."
cd ~/byhaider-homepage
echo "📥 Pull latest changes for byhaider-homepage..."
git pull origin main
echo "🛑 Stoppe alte Container..."
docker compose down
echo "📦 Baue Images neu..."
docker compose build
echo "⬆️ Starte Container..."
docker compose up -d
echo "🧹 Bereinige alte Images..."
docker image prune -f
echo "✅ Deployment abgeschlossen!"
docker compose ps

11
nginx.conf Normal file
View File

@@ -0,0 +1,11 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri /index.html;
}
}

View File

@@ -1,6 +1,12 @@
{ {
"common": { "common": {
"home": "Startseite", "home": "Startseite",
"about": "Über mich" "about": "Über mich",
"projects": "Projekte",
"copyright": "© 2025 Nico Haider; Alle Rechte vorbehalten."
},
"home": {
"header": "Hi, ich bin<br/>Nico HAIDER.",
"subheader": "Softwareentwickler für Webseiten, Web-Apps, Mobile-Apps, Desktop-Apps und vieles mehr."
} }
} }

View File

@@ -1,6 +1,12 @@
{ {
"common": { "common": {
"home": "Home", "home": "Home",
"about": "About" "about": "About",
"projects": "Projects",
"copyright": "© 2025 Nico Haider; All rights reserved."
},
"home": {
"header": "Hi, I'm<br/>Nico HAIDER.",
"subheader": "Software developer for websites, web apps, mobile apps, desktop apps and much more."
} }
} }

BIN
public/img/me.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
public/img/page-in-work.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 KiB

View File

@@ -323,17 +323,17 @@ export const Theme = definePreset(Aura, {
transitionDuration: "{transition.duration}" transitionDuration: "{transition.duration}"
}, },
primary: { primary: {
50: "#fffdea", 50: "#fff9ec",
100: "#fff7c2", 100: "#fff3d4",
200: "#ffef85", 200: "#ffe7a8",
300: "#ffe24d", 300: "#ffdb70", // deine gewünschte Farbe als Kern
400: "#ffd700", 400: "#ffcf38",
500: "#e6c200", 500: "#ffdb70", // Hauptfarbe
600: "#bfa100", 600: "#e6c35f",
700: "#997f00", 700: "#bf9e4a",
800: "#735f00", 800: "#997a36",
900: "#4d3f00", 900: "#735625",
950: "#1f1600" 950: "#4d3817"
}, },
colorScheme: { colorScheme: {
light: { light: {

View File

@@ -1,3 +1,11 @@
<div class="flex flex-col min-h-screen">
<app-background/> <app-background/>
<main class="flex-1">
<app-navigation-bar/> <app-navigation-bar/>
<router-outlet/> <router-outlet></router-outlet>
</main>
<p class="text-gray text-center p-5">
{{ 'common.copyright' | translate }}
</p>
</div>

View File

@@ -1,9 +1,11 @@
import { Routes } from '@angular/router'; import { Routes } from '@angular/router';
import { Home } from './pages/home/home'; import { Home } from './pages/home/home';
import { About } from './pages/about/about'; import { About } from './pages/about/about';
import { Projects } from './pages/projects/projects';
export const routes: Routes = [ export const routes: Routes = [
{ path: '', component: Home }, { path: '', component: Home },
{ path: 'about', component: About }, { path: 'about', component: About },
{ path: 'projects', component: Projects },
{ path: '**', redirectTo: '', pathMatch: 'full' }, { path: '**', redirectTo: '', pathMatch: 'full' },
]; ];

View File

@@ -3,10 +3,11 @@ import { RouterOutlet } from '@angular/router';
import { ThemeSwitchService } from './core/service/theme-switch.service'; import { ThemeSwitchService } from './core/service/theme-switch.service';
import { Background } from "./core/components/background/background"; import { Background } from "./core/components/background/background";
import { NavigationBar } from "./core/components/navigation-bar/navigation-bar"; import { NavigationBar } from "./core/components/navigation-bar/navigation-bar";
import { TranslatePipe } from '@ngx-translate/core';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
imports: [RouterOutlet, Background, NavigationBar], imports: [RouterOutlet, Background, NavigationBar, TranslatePipe],
templateUrl: './app.html', templateUrl: './app.html',
}) })
export class App { export class App {

View File

@@ -16,11 +16,11 @@ export class Background {
@ViewChild('canvas', { static: true }) canvasRef!: ElementRef<HTMLCanvasElement>; @ViewChild('canvas', { static: true }) canvasRef!: ElementRef<HTMLCanvasElement>;
// Config // Config
private numStars = 150; private numStars = 400;
private minBlink = 0.2; private minBlink = 0.2;
private maxBlink = 1; private maxBlink = 1;
private blinkSpeed = 0.002; // Stern blinkt langsamer oder schneller private blinkSpeed = 0.002; // Stern blinkt langsamer oder schneller
private maxSpeed = 0.1; // Sternbewegungsgeschwindigkeit private maxSpeed = .8; // Sternbewegungsgeschwindigkeit
private parallaxFactor = 0.5; // Scroll-Parallax-Faktor private parallaxFactor = 0.5; // Scroll-Parallax-Faktor
// Feature toggles // Feature toggles
@@ -33,17 +33,24 @@ export class Background {
private height = window.innerHeight; private height = window.innerHeight;
private animationId!: number; private animationId!: number;
private scrollY = window.scrollY; private scrollY = window.scrollY;
private bodyHeight = document.body.scrollHeight;
ngOnInit() { ngAfterViewInit() {
requestAnimationFrame(() => {
const canvas = this.canvasRef.nativeElement; const canvas = this.canvasRef.nativeElement;
this.ctx = canvas.getContext('2d')!; this.ctx = canvas.getContext('2d')!;
this.width = window.innerWidth;
this.height = window.innerHeight;
canvas.width = this.width; canvas.width = this.width;
canvas.height = this.height; canvas.height = this.height;
for (let i = 0; i < (this.numStars) * (document.body.scrollHeight / this.height); i++) { this.bodyHeight = document.body.scrollHeight + 110; // navbar height
for (let i = 0; i < this.numStars * (this.bodyHeight / this.height); i++) {
this.stars.push({ this.stars.push({
x: Math.random() * this.width, x: Math.random() * this.width,
y: Math.random() * document.body.scrollHeight, y: Math.random() * this.bodyHeight,
radius: Math.random() * 1.5 + 0.5, radius: Math.random() * 1.5 + 0.5,
alpha: this.minBlink + Math.random() * (this.maxBlink - this.minBlink), alpha: this.minBlink + Math.random() * (this.maxBlink - this.minBlink),
alphaChange: (Math.random() * this.blinkSpeed) + 0.0005, alphaChange: (Math.random() * this.blinkSpeed) + 0.0005,
@@ -53,6 +60,7 @@ export class Background {
} }
this.animate(); this.animate();
});
} }
@HostListener('window:resize') @HostListener('window:resize')
@@ -89,15 +97,15 @@ export class Background {
// Bildschirm-Ränder // Bildschirm-Ränder
if (star.x < 0) star.x = this.width; if (star.x < 0) star.x = this.width;
if (star.x > this.width) star.x = 0; if (star.x > this.width) star.x = 0;
if (star.y < 0) star.y = document.body.scrollHeight; if (star.y < 0) star.y = this.bodyHeight;
if (star.y > document.body.scrollHeight) star.y = 0; if (star.y > this.bodyHeight) star.y = 0;
// Stern zeichnen mit Scroll-Parallax // Stern zeichnen mit Scroll-Parallax
ctx.beginPath(); ctx.beginPath();
ctx.arc(star.x, star.y - this.scrollY * this.parallaxFactor, star.radius, 0, Math.PI * 2); ctx.arc(star.x, star.y - this.scrollY * this.parallaxFactor, star.radius, 0, Math.PI * 2);
ctx.fillStyle = this.themeSwitchService.darkMode() ctx.fillStyle = this.themeSwitchService.darkMode()
? `rgba(255, 215, 0, ${star.alpha})` ? `rgba(191, 158, 74, ${star.alpha})`
: `rgba(184, 134, 11, ${star.alpha})`; : `rgba(255, 219, 112, ${star.alpha})`;
ctx.fill(); ctx.fill();
} }

View File

@@ -1,10 +1,10 @@
<nav class="sticky top-0 p-[30px] flex flex-row justify-between relative z-5000"> <nav class="sticky top-0 p-[30px] flex flex-row justify-between relative z-30">
<div class="logo grid place-items-center"> <div class="logo grid place-items-center">
<span class="font-semibold text-3xl"> <span class="font-semibold text-3xl">
<img [src]="themeSwitchService.darkMode() ? 'logo/square_white.svg' : 'logo/square_black.svg'" alt="bH" width="50"> <a routerLink="/"><img [src]="themeSwitchService.darkMode() ? 'logo/square_white.svg' : 'logo/square_black.svg'" alt="bH" width="50"></a>
</span> </span>
</div> </div>
<div class="navigation grid place-items-center"> <div class="navigation place-items-center hidden md:grid">
<ul> <ul>
<li class="relative list-none flex flex-row gap-3"> <li class="relative list-none flex flex-row gap-3">
<a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }"> <a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">
@@ -13,10 +13,13 @@
<a routerLink="/about" routerLinkActive="active"> <a routerLink="/about" routerLinkActive="active">
{{ 'common.about' | translate }} {{ 'common.about' | translate }}
</a> </a>
<a routerLink="/projects" routerLinkActive="active">
{{ 'common.projects' | translate }}
</a>
</li> </li>
</ul> </ul>
</div> </div>
<div class="options flex flex-row gap-[10px] items-center"> <div class="options flex-row gap-[10px] items-center hidden md:flex">
@if (themeSwitchService.darkMode()) { @if (themeSwitchService.darkMode()) {
<div class="dark-mode size-[50px]" (click)="themeSwitchService.switchToLight()"> <div class="dark-mode size-[50px]" (click)="themeSwitchService.switchToLight()">
<fa-icon [icon]="faMoon"/> <fa-icon [icon]="faMoon"/>
@@ -30,7 +33,44 @@
{{ translateService.getCurrentLang().toUpperCase() }} {{ translateService.getCurrentLang().toUpperCase() }}
</div> </div>
</div> </div>
<p-button icon="fa-solid fa-bars" outlined (click)="showMobileMenu.set(true)" class="block md:hidden"/>
</nav> </nav>
<div class="blur blur1"></div> @if (showMobileMenu()) {
<div class="blur blur2"></div> <div class="mobile-menu block md:hidden w-full h-full fixed top-0 left-0 z-50">
<p-button icon="fa-solid fa-x" outlined (click)="showMobileMenu.set(false)" class="absolute top-8 right-8"/>
<ul class="h-full p-[100px]">
<li class="h-full relative list-none flex flex-col gap-3 align-center justify-center text-center">
<a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }" (click)="showMobileMenu.set(false)">
{{ 'common.home' | translate }}
</a>
<a routerLink="/about" routerLinkActive="active" (click)="showMobileMenu.set(false)">
{{ 'common.about' | translate }}
</a>
<a routerLink="/projects" routerLinkActive="active" (click)="showMobileMenu.set(false)">
{{ 'common.projects' | translate }}
</a>
<hr class="h-[1px] w-[80%] bg-(--content-color) mx-auto"/>
<div class="options flex flex-row gap-[10px] items-center justify-center">
@if (themeSwitchService.darkMode()) {
<div class="dark-mode size-[50px]" (click)="themeSwitchService.switchToLight()">
<fa-icon [icon]="faMoon"/>
</div>
} @else {
<div class="dark-mode size-[50px]" (click)="themeSwitchService.switchToDark()">
<fa-icon [icon]="faSun"/>
</div>
}
<div class="language size-[50px]" (click)="toggleLanguage()">
{{ translateService.getCurrentLang().toUpperCase() }}
</div>
</div>
</li>
</ul>
</div>
<div class="block md:hidden w-full h-full fixed top-0 left-0 z-40 backdrop-blur-md"></div>
}
<div class="z-10 backdrop-blur-xl fixed top-0 left-0 w-full h-[150px] mask-b-from-70%"></div>

View File

@@ -1,6 +1,3 @@
nav {
background-color: rgb(from var(--content-background) r g b / 0.5);
.options > div { .options > div {
display: grid; display: grid;
place-items: center; place-items: center;
@@ -10,15 +7,15 @@ nav {
transition: border .5s ease; transition: border .5s ease;
&:hover { &:hover {
border-color: var(--content-hover-background); border-color: rgb(from var(--content-color) r g b / 0.5);
} }
&:active { &:active {
border-color: var(--content-border-color); border-color: var(--content-color);
} }
} }
.navigation ul li a { ul li a {
display: block; display: block;
padding: 7.5px 15px; padding: 7.5px 15px;
position: relative; position: relative;
@@ -36,27 +33,8 @@ nav {
border: 1px solid var(--primary-500); border: 1px solid var(--primary-500);
} }
} }
}
.blur { .mobile-menu ul li a {
position: fixed; font-size: 1rem;
top: 0; padding: 15px 30px;
left: 0;
width: 100%;
height: 120px;
pointer-events: none;
}
.blur1 {
z-index: 10;
backdrop-filter: blur(3px);
mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 40%, rgba(0, 0, 0, 1) 70%, rgba(0, 0, 0, 0) 100%);
-webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 40%, rgba(0, 0, 0, 1) 70%, rgba(0, 0, 0, 0) 100%);
}
.blur2 {
z-index: 20;
backdrop-filter: blur(5px);
mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, 1) 85%, rgba(0, 0, 0, 1) 100%);
-webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, 1) 85%, rgba(0, 0, 0, 1) 100%);
} }

View File

@@ -1,14 +1,15 @@
import { Component, inject } from '@angular/core'; import { Component, inject, signal } from '@angular/core';
import { Router, RouterLink, RouterLinkActive } from '@angular/router'; import { Router, RouterLink, RouterLinkActive } from '@angular/router';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { faMoon } from '@fortawesome/free-solid-svg-icons'; import { faMoon } from '@fortawesome/free-solid-svg-icons';
import { faSun } from '@fortawesome/free-solid-svg-icons'; import { faSun } from '@fortawesome/free-solid-svg-icons';
import { ThemeSwitchService } from '../../service/theme-switch.service'; import { ThemeSwitchService } from '../../service/theme-switch.service';
import { TranslatePipe, TranslateService } from '@ngx-translate/core'; import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { ButtonModule } from "primeng/button";
@Component({ @Component({
selector: 'app-navigation-bar', selector: 'app-navigation-bar',
imports: [FontAwesomeModule, RouterLink, RouterLinkActive, TranslatePipe], imports: [FontAwesomeModule, RouterLink, RouterLinkActive, TranslatePipe, ButtonModule],
templateUrl: './navigation-bar.html', templateUrl: './navigation-bar.html',
styleUrl: './navigation-bar.scss' styleUrl: './navigation-bar.scss'
}) })
@@ -18,6 +19,8 @@ export class NavigationBar {
protected themeSwitchService = inject(ThemeSwitchService); protected themeSwitchService = inject(ThemeSwitchService);
protected translateService = inject(TranslateService); protected translateService = inject(TranslateService);
showMobileMenu = signal(false);
constructor() {} constructor() {}
isActive(route: string): boolean { isActive(route: string): boolean {

View File

@@ -1 +1,6 @@
<p>about works!</p> <div class="text-center mt-5">
<p>Nico Haider</p>
<p>3843 Dobersberg</p>
<p>Portfolio</p>
</div>
<img src="img/page-in-work.jpg" alt="" class="w-[200px] mx-auto mt-10"/>

View File

@@ -1 +1,21 @@
<p>home works!</p> <main class="flex flex-row flex-wrap justify-center items-center gap-10 py-10"
pAnimateOnScroll
enterClass="animate-enter fade-in-10 slide-in-from-t-8 animate-duration-1000">
<div class="lg:w-[40%] w-[80%] text-center lg:text-left">
<span class="block text-[3rem]/[1.1] lg:text-[4rem]/[1.1] font-bold mb-4" [innerHTML]="'home.header' | translate"></span>
<span class="block text-[1rem]/[1.3] lg:text-[1.5rem]/[1.3] text-gray">{{ 'home.subheader' | translate }}</span>
<a class="block mt-5" href="https://www.google.com/maps/place/Dobersberg,+Nieder%C3%B6sterreich" target="_blank"><p-chip label="Dobersberg, Niederösterreich" icon="fa-solid fa-location-dot"/></a>
</div>
<div class="lg:w-[30%] w-[80%] text-center">
<img src="img/me.png" alt="">
<div class="pt-5 p-3 flex gap-3 flex-wrap justify-center">
<a pButton outlined severity="secondary" label="nico@td-haider.at" icon="fa-solid fa-envelope" href="mailto:nico@td-haider.at"></a>
<a pButton outlined severity="secondary" label="+43 670 2060140" icon="fa-solid fa-phone" href="tel:+436702060140"></a>
</div>
<div class="flex gap-3 justify-center text-[1.5rem] text-gray">
<a pButton text severity="secondary" icon="fa-brands fa-linkedin" href="https://www.linkedin.com/in/nico-haider-164444316/" target="_blank"></a>
<a pButton text severity="secondary" icon="fa-brands fa-instagram" href="https://www.instagram.com/nico.hdr8/" target="_blank"></a>
<a pButton text severity="secondary" icon="fa-brands fa-facebook" href="https://www.facebook.com/nico.haider.33" target="_blank"></a>
</div>
</div>
</main>

View File

@@ -0,0 +1,6 @@
main {
img {
filter: drop-shadow(0 0 15px rgb(from var(--primary-color) r g b / 0.1));
mask-image: linear-gradient(to bottom, rgba(0,0,0,1) 60%, rgba(0,0,0,0) 100%);
}
}

View File

@@ -1,8 +1,13 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { TranslatePipe } from '@ngx-translate/core';
import { ChipModule } from 'primeng/chip';
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { ButtonModule } from 'primeng/button';
import { AnimateOnScrollModule } from 'primeng/animateonscroll';
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
imports: [], imports: [TranslatePipe, ChipModule, FontAwesomeModule, ButtonModule, AnimateOnScrollModule],
templateUrl: './home.html', templateUrl: './home.html',
styleUrl: './home.scss' styleUrl: './home.scss'
}) })

View File

@@ -0,0 +1 @@
<img src="img/page-in-work.jpg" alt="" class="w-[200px] mx-auto mt-10"/>

View File

View File

@@ -0,0 +1,17 @@
import { Component } from '@angular/core';
import { TranslatePipe } from '@ngx-translate/core';
import { ChipModule } from 'primeng/chip';
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { ButtonModule } from 'primeng/button';
@Component({
selector: 'app-home',
imports: [],
templateUrl: './projects.html',
styleUrl: './projects.scss'
})
export class Projects {
}

View File

@@ -1,4 +1,5 @@
@use "tailwindcss"; @use "tailwindcss";
@plugin "tailwindcss-primeui";
@import '@fontsource-variable/open-sans/wght.css'; @import '@fontsource-variable/open-sans/wght.css';
@import '@fontsource-variable/jetbrains-mono/wght.css'; @import '@fontsource-variable/jetbrains-mono/wght.css';
@import '@fortawesome/fontawesome-free/css/all.css'; @import '@fortawesome/fontawesome-free/css/all.css';
@@ -9,11 +10,6 @@ body {
margin: 0; margin: 0;
font-size: 14px; font-size: 14px;
overflow: auto; overflow: auto;
background-color: var(--primary-50);
}
html.dark body {
background-color: var(--surface-950);
} }
p-card { p-card {
@@ -26,3 +22,7 @@ p-card {
padding: 0; padding: 0;
} }
} }
.text-gray {
color: rgb(from var(--content-color) r g b / 0.7);
}