Compare commits
1 Commits
senpai
...
393290441c
| Author | SHA1 | Date | |
|---|---|---|---|
| 393290441c |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,2 +0,0 @@
|
|||||||
*.md linguist-language=Astro
|
|
||||||
*.mdx linguist-language=Astro
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Deploy Dev Website
|
name: Deploy Astro
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@@ -9,30 +9,30 @@ jobs:
|
|||||||
name: Build and Deploy
|
name: Build and Deploy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
# services:
|
services:
|
||||||
# mermaid:
|
mermaid:
|
||||||
# image: yuzutech/kroki-mermaid
|
image: yuzutech/kroki-mermaid
|
||||||
# kroki:
|
kroki:
|
||||||
# image: yuzutech/kroki
|
image: yuzutech/kroki
|
||||||
# env:
|
env:
|
||||||
# KROKI_MERMAID_HOST: mermaid
|
KROKI_MERMAID_HOST: mermaid
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
name: Checkout code
|
name: Checkout code
|
||||||
|
|
||||||
- name: Setup node and npm
|
- name: Setup node and npm
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: lts/*
|
node-version: lts/*
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm install
|
run: npm ci
|
||||||
|
|
||||||
- name: Check and build
|
- name: Check and build
|
||||||
run: npm run build
|
run: npm run build
|
||||||
# env:
|
env:
|
||||||
# KROKI_SERVER: "http://kroki:8000"
|
KROKI_SERVER: "http://kroki"
|
||||||
|
|
||||||
- name: Copy files via ssh
|
- name: Copy files via ssh
|
||||||
uses: appleboy/scp-action@v1
|
uses: appleboy/scp-action@v1
|
||||||
@@ -41,6 +41,6 @@ jobs:
|
|||||||
username: ${{ secrets.SSH_USERNAME }}
|
username: ${{ secrets.SSH_USERNAME }}
|
||||||
key: ${{ secrets.SSH_KEY }}
|
key: ${{ secrets.SSH_KEY }}
|
||||||
source: "dist/*"
|
source: "dist/*"
|
||||||
target: /srv/website/stable
|
target: /srv/website/dev
|
||||||
overwrite: true
|
overwrite: true
|
||||||
strip_components: 1
|
strip_components: 1
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
name: Deploy Stable Website
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- senpai
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-deploy:
|
|
||||||
name: Build and Deploy
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
# services:
|
|
||||||
# mermaid:
|
|
||||||
# image: yuzutech/kroki-mermaid
|
|
||||||
# kroki:
|
|
||||||
# image: yuzutech/kroki
|
|
||||||
# env:
|
|
||||||
# KROKI_MERMAID_HOST: mermaid
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
name: Checkout code
|
|
||||||
|
|
||||||
- name: Setup node and npm
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: lts/*
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: Check and build
|
|
||||||
run: npm run build
|
|
||||||
# env:
|
|
||||||
# KROKI_SERVER: "http://kroki:8000"
|
|
||||||
|
|
||||||
- name: Copy files via ssh
|
|
||||||
uses: appleboy/scp-action@v1
|
|
||||||
with:
|
|
||||||
host: c0ntroller.de
|
|
||||||
username: ${{ secrets.SSH_USERNAME }}
|
|
||||||
key: ${{ secrets.SSH_KEY }}
|
|
||||||
source: "dist/*"
|
|
||||||
target: /srv/website/stable
|
|
||||||
overwrite: true
|
|
||||||
strip_components: 1
|
|
||||||
46
README.md
46
README.md
@@ -1,13 +1,43 @@
|
|||||||
# Frontpage
|
# Astro Starter Kit: Minimal
|
||||||
|
|
||||||
[](https://c0ntroller.de/portfolio/astro-rewrite/)
|
```sh
|
||||||
|
npm create astro@latest -- --template minimal
|
||||||
|
```
|
||||||
|
|
||||||
| Stable | Dev
|
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||||
| ------ | ---
|
|
||||||
| [](https://c0ntroller.de/) | [](https://dev.c0ntroller.de/)
|
|
||||||
|
|
||||||
This repository contains my Astro-based website.
|
## 🚀 Project Structure
|
||||||
|
|
||||||
When changes are made to `senpai` it will be deploy on https://c0ntroller.de
|
Inside of your Astro project, you'll see the following folders and files:
|
||||||
|
|
||||||
When changes are made in the `dev` branch it will be deployed on https://dev.c0ntroller.de
|
```text
|
||||||
|
/
|
||||||
|
├── public/
|
||||||
|
├── src/
|
||||||
|
│ └── pages/
|
||||||
|
│ └── index.astro
|
||||||
|
└── package.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||||
|
|
||||||
|
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||||
|
|
||||||
|
Any static assets, like images, can be placed in the `public/` directory.
|
||||||
|
|
||||||
|
## 🧞 Commands
|
||||||
|
|
||||||
|
All commands are run from the root of the project, from a terminal:
|
||||||
|
|
||||||
|
| Command | Action |
|
||||||
|
| :------------------------ | :----------------------------------------------- |
|
||||||
|
| `npm install` | Installs dependencies |
|
||||||
|
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||||
|
| `npm run build` | Build your production site to `./dist/` |
|
||||||
|
| `npm run preview` | Preview your build locally, before deploying |
|
||||||
|
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||||
|
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||||
|
|
||||||
|
## 👀 Want to learn more?
|
||||||
|
|
||||||
|
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ const currentPath = Astro.url.pathname;
|
|||||||
import Logo from "../assets/logo.svg";
|
import Logo from "../assets/logo.svg";
|
||||||
---
|
---
|
||||||
|
|
||||||
<nav class="main-nav glass-container" style="view-transition-name:navigation;">
|
<nav class="main-nav glass-container">
|
||||||
<div class="nav-content">
|
<div class="nav-content">
|
||||||
<a href="/" class="logo">
|
<a href="/" class="logo">
|
||||||
<Logo class="logo-img" />
|
<Logo class="logo-img" />
|
||||||
<span class="logo-text">c0ntroller.de</span>
|
c0ntroller.de
|
||||||
</a>
|
</a>
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<a
|
<a
|
||||||
@@ -25,6 +25,21 @@ import Logo from "../assets/logo.svg";
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
body:has(nav a[href="/"]:hover) {
|
||||||
|
--accent-base: var(--accent-base--default);
|
||||||
|
}
|
||||||
|
body:has(nav a[href="/portfolio"]:hover) {
|
||||||
|
--accent-base: var(--accent-base--portfolio);
|
||||||
|
}
|
||||||
|
body:has(nav a[href="/blog"]:hover) {
|
||||||
|
--accent-base: var(--accent-base--blog);
|
||||||
|
}
|
||||||
|
body:has(nav a[href="/book"]:hover) {
|
||||||
|
--accent-base: var(--accent-base--book);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.main-nav {
|
.main-nav {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
@@ -83,13 +98,4 @@ import Logo from "../assets/logo.svg";
|
|||||||
color: rgb(var(--accent-base));
|
color: rgb(var(--accent-base));
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
|
||||||
.logo-text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.links {
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
.welcome-typewriter-nostyle {
|
.welcome-typewriter-nostyle {
|
||||||
min-height: 1em;
|
min-height: 1em;
|
||||||
border-right: 2px solid rgb(var(--accent-base));
|
border-right: 2px solid orange;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: block;
|
display: block;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
width: 0px;
|
width: 0px;
|
||||||
border-right: 2px solid rgb(var(--accent-base));
|
border-right: 2px solid orange;
|
||||||
animation: blink-caret 1s step-end infinite;
|
animation: blink-caret 1s step-end infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes blink-caret {
|
@keyframes blink-caret {
|
||||||
from, to { border-color: rgb(var(--accent-base)) }
|
from, to { border-color: orange }
|
||||||
50% { border-color: transparent; }
|
50% { border-color: transparent; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ const portfolioCollection = defineCollection({
|
|||||||
summary: z.string(),
|
summary: z.string(),
|
||||||
tags: z.array(z.string()).optional(),
|
tags: z.array(z.string()).optional(),
|
||||||
pubDate: z.date(),
|
pubDate: z.date(),
|
||||||
repository: z.url().regex(/git/).optional(),
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,65 +2,10 @@
|
|||||||
title: Astro Rewrite
|
title: Astro Rewrite
|
||||||
summary: "Next.js entwickelt sich rasend - zu schnell für mich, um Features und Sicherheitsupdates immer zu verfolgen. Und React für einen Blog? Unnötig. Eine einfache statische Lösung aber mit Komponenten? Astro ist genau das. Also: Willkommen zum neuen Anstrich in Astro!"
|
summary: "Next.js entwickelt sich rasend - zu schnell für mich, um Features und Sicherheitsupdates immer zu verfolgen. Und React für einen Blog? Unnötig. Eine einfache statische Lösung aber mit Komponenten? Astro ist genau das. Also: Willkommen zum neuen Anstrich in Astro!"
|
||||||
repository: "https://git.c0ntroller.de/c0ntroller/frontpage"
|
repository: "https://git.c0ntroller.de/c0ntroller/frontpage"
|
||||||
pubDate: 2025-03-22
|
pubDate: 2023-04-03
|
||||||
tags:
|
tags:
|
||||||
- Astro
|
- Astro
|
||||||
|
- SSR
|
||||||
- Webentwicklung
|
- Webentwicklung
|
||||||
---
|
---
|
||||||
|
|
||||||
Next.js war einfach Magie.
|
|
||||||
Als ich React lernte und noch überlegte, wie ich am besten ein Backend dazu stelle, fragete ein Freund, warum ich nicht einfach Next.js nehme.
|
|
||||||
Und das war magisch.
|
|
||||||
Denn ich konnte mein Gelerntes nutzen und hatte trotzdem direkt ein Backend mit dabei.
|
|
||||||
Ich hab mir darin nicht nur ein kleines Projekt gebaut, sondern später auch meine erste Website.
|
|
||||||
|
|
||||||
Die Struktur war einfach: Eine Datei in `app` anlegen und... Moment.
|
|
||||||
Stimmt gar nicht mehr.
|
|
||||||
Also: Eine Datei in `pages` anlegen. Oder doch in `app`?
|
|
||||||
Beides Ok.
|
|
||||||
Achso, außer dass `app` dann deprecated wurde.
|
|
||||||
|
|
||||||
Next.js war für mich die erste Berührung mit dem JavaScript Ökosystem und plötzlich verstand ich die ganzen Memes.
|
|
||||||
Dann kam auch plötzlich die Nachricht vom dependebot und ich hatte plötzlich 20 PRs, die alle Next.js Updates waren.
|
|
||||||
Nur, dass ab irgendeinem Punkt man plötzlich sich mit komplizierteren Updates rumschlagen musste und nicht einfach nur `npm audit fix` machen konnte.
|
|
||||||
|
|
||||||
Also brauchte es eine Alternative.
|
|
||||||
|
|
||||||
## Sinneswandel
|
|
||||||
|
|
||||||
React ist cool.
|
|
||||||
Ziemlich performant für das, was es macht, sehr flexibel und einmal gelernt kann man auch andere Frameworks leicht lernen.
|
|
||||||
|
|
||||||
Aber wofür braucht eine Homepage eine komplexe reaktive Komponente?
|
|
||||||
Naja, eigentlich braucht sie das nicht.
|
|
||||||
Aber es war an dem Punkt für mich die einzige Möglichkeit absiets von Vanilla HTML5, CSS und JS zu arbeiten.
|
|
||||||
|
|
||||||
Gleichzeitig merkte ich bei immer mehr Seiten, dass hier Unmengen an Rechenleistung in JavaScript nur für hübsche Effekte drauf ging.
|
|
||||||
Ich bin sehr für schöne Effekte, aber immer mehr fand ich, dass man als **guter** Web Entwickler eigentlich so wenig JavaScript wie möglich einsetzen sollte.
|
|
||||||
JavaScript Frameworks sind im Normalfall aber das genaue Gegenteil.
|
|
||||||
|
|
||||||
Ich wollte meine Seite also neu machen und hatte eien Vision, die nicht ganz erreichbar erschien.
|
|
||||||
Und dann fand ich ein Framework, dass eigentlich genau das war, was ich suchte: Astro.
|
|
||||||
|
|
||||||
## Astro
|
|
||||||
|
|
||||||
Astro zeichnet sich dadurch aus, dass es komplett statische Seiten generiert.
|
|
||||||
Falls man das braucht, kann man aber auch Server Side Rendering nutzen, oder sogar beides gleichzeitig.
|
|
||||||
Islands gibt es sogar für die verschiedensten Frameworks.
|
|
||||||
|
|
||||||
Aber all das brauchte ich gar nicht.
|
|
||||||
Eine cleane modulare Webseite aufbauen, mit verschachtelten Komponenten, scoped CSS und ohne JavaScript, dass man nicht selbst schreibt.
|
|
||||||
Das war genau das, was ich suchte.
|
|
||||||
|
|
||||||
Und so habe ich mich an die Arbeit gemacht, meine Seite neu zu bauen.
|
|
||||||
Und gebaut.
|
|
||||||
Und gebaut.
|
|
||||||
Und gebaut...
|
|
||||||
|
|
||||||
Tja ich fing an zu arbeiten und plötzlich war da gar nicht mehr so viel Zeit.
|
|
||||||
|
|
||||||
Aber nach wirklich langer Zeit und viel Arbeit ist es jetzt endlich soweit - die neue Seite ist hübsch, sehr schnell, hat vollen Score bei Lighthouse und ist komplett in Astro gebaut.
|
|
||||||
Ich bin sehr zufrieden damit.
|
|
||||||
|
|
||||||
Vielleicht kommt irgendwann ja nochmal wieder ein Terminal dazu, dass ich früher als Webseite hatte.
|
|
||||||
Aber vorerst genieße ich es erstmal wieder eine eine hübsche und schnelle Seite zu haben.
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ const {
|
|||||||
<html lang="de">
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<meta name="description" content={description} />
|
<meta name="description" content={description} />
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ const { entry } = Astro.props;
|
|||||||
const { Content } = await render(entry);
|
const { Content } = await render(entry);
|
||||||
---
|
---
|
||||||
<BaseLayout title={entry.data.title} theme="blog">
|
<BaseLayout title={entry.data.title} theme="blog">
|
||||||
<div class="glass-container header" style={`view-transition-name: blog-header-${entry.id};`}>
|
<div class="glass-container header">
|
||||||
<h1 style={`view-transition-name: blog-headline-${entry.id};`}>{entry.data.title}</h1>
|
<h1>{entry.data.title}</h1>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<time style={`view-transition-name: blog-pubdate-${entry.id};`}>{entry.data.pubDate.toLocaleDateString()}</time>
|
<time>{entry.data.pubDate.toLocaleDateString()}</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ const posts = await getCollection('blog');
|
|||||||
posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
|
posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
|
||||||
---
|
---
|
||||||
<BaseLayout title="Blog" theme="blog" description="Gedanken über Technologie, Design und das Leben von c0ntroller.de.">
|
<BaseLayout title="Blog" theme="blog" description="Gedanken über Technologie, Design und das Leben von c0ntroller.de.">
|
||||||
<div class="glass-container header" style="view-transition-name:main-glass;">
|
<div class="glass-container header">
|
||||||
<h1>Artikel & Gedanken</h1>
|
<h1>Artikel & Gedanken</h1>
|
||||||
<p>Gedanken über Technologie, Design und das Leben.</p>
|
<p>Gedanken über Technologie, Design und das Leben.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list">
|
<div class="list">
|
||||||
{posts.map(post => (
|
{posts.map(post => (
|
||||||
<a href={`/blog/${post.id}`} class="glass-container link-card" style={`view-transition-name: blog-header-${post.id};`}>
|
<a href={`/blog/${post.id}`} class="glass-container link-card">
|
||||||
<h2 style={`view-transition-name: blog-headline-${post.id};`}>{post.data.title}</h2>
|
<h2>{post.data.title}</h2>
|
||||||
<time class="date" style={`view-transition-name: blog-pubdate-${post.id};`}>{post.data.pubDate.toLocaleDateString()}</time>
|
<p class="date">{post.data.pubDate.toLocaleDateString()}</p>
|
||||||
<p>{post.data.summary}</p>
|
<p>{post.data.summary}</p>
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ const chapters = allPages.reduce((acc, p) => {
|
|||||||
}, {} as Record<string, typeof allPages>);
|
}, {} as Record<string, typeof allPages>);
|
||||||
---
|
---
|
||||||
<BaseLayout title={page.data.title} theme="book">
|
<BaseLayout title={page.data.title} theme="book">
|
||||||
<div class="glass-container content prose" style="view-transition-name:main-glass;">
|
<div class="glass-container content prose">
|
||||||
<h1 style={`view-transition-name: book-headline-${page.id.replaceAll("/", "-")};`}>{page.data.title}</h1>
|
<h1>{page.data.title}</h1>
|
||||||
<Content />
|
<Content />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const chapters = pages.reduce((acc, page) => {
|
|||||||
}, {} as Record<string, typeof pages>);
|
}, {} as Record<string, typeof pages>);
|
||||||
---
|
---
|
||||||
<BaseLayout title="Das Buch" theme="book" description="Ein fortlaufendes Werk über Software, Design und Architektur von c0ntroller.de.">
|
<BaseLayout title="Das Buch" theme="book" description="Ein fortlaufendes Werk über Software, Design und Architektur von c0ntroller.de.">
|
||||||
<div class="glass-container header" style="view-transition-name:main-glass;">
|
<div class="glass-container header">
|
||||||
<h1>Das Buch</h1>
|
<h1>Das Buch</h1>
|
||||||
<p>Ein fortlaufendes Werk über Software, Design und Architektur.</p>
|
<p>Ein fortlaufendes Werk über Software, Design und Architektur.</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -25,7 +25,7 @@ const chapters = pages.reduce((acc, page) => {
|
|||||||
<h3>{chapter.replace(/-/g, ' ').toUpperCase()}</h3>
|
<h3>{chapter.replace(/-/g, ' ').toUpperCase()}</h3>
|
||||||
<ul class="page-list">
|
<ul class="page-list">
|
||||||
{items.map(item => (
|
{items.map(item => (
|
||||||
<li><a href={`/book/${item.id}`} style={`view-transition-name: book-headline-${item.id.replaceAll("/", "-")};`}>{item.data.title}</a></li>
|
<li><a href={`/book/${item.id}`}>{item.data.title}</a></li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
---
|
---
|
||||||
import WelcomeTypewriter from "../components/WelcomeTypewriter.astro";
|
import WelcomeTypewriter from '../components/WelcomeTypewriter.astro';
|
||||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
import { Icon } from "astro-icon/components";
|
import { Icon } from 'astro-icon/components';
|
||||||
import socials from "../data/socials.json";
|
import socials from "../data/socials.json";
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title="c0ntroller.de" theme="default">
|
<BaseLayout title="c0ntroller.de" theme="default">
|
||||||
<div class="landing-wrapper">
|
<div class="landing-wrapper">
|
||||||
<div class="hero-section">
|
<div class="hero-section">
|
||||||
<div class="socials fade-in-up shadow-glow glass-bg glass-container">
|
<div class="socials fade-in-up shadow-glow glass-bg glass-container">
|
||||||
{
|
{socials.map(({ name, url, icon }) => (
|
||||||
socials.map(({ name, url, icon }) => (
|
<a href={url} target="_blank" rel="noreferrer" class="social-link">
|
||||||
<a href={url} target="_blank" referrerpolicy="no-referrer" class="social-link">
|
|
||||||
<Icon name={icon} desc={name} />
|
<Icon name={icon} desc={name} />
|
||||||
</a>
|
</a>
|
||||||
))
|
))}
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<h1 class="gradient-text reveal-text">Willkommen auf meiner Seite.</h1>
|
<h1 class="gradient-text reveal-text">Willkommen auf meiner Seite.</h1>
|
||||||
<p class="subtitle fade-in-up">Hier geht es unter anderem um:</p>
|
<p class="subtitle fade-in-up">
|
||||||
|
Hier geht es unter anderem um:
|
||||||
|
</p>
|
||||||
<WelcomeTypewriter class="fade-in-up" />
|
<WelcomeTypewriter class="fade-in-up" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -83,7 +82,7 @@ import socials from "../data/socials.json";
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.5rem;
|
gap: .5rem;
|
||||||
margin: 0 auto 2rem auto;
|
margin: 0 auto 2rem auto;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
backdrop-filter: blur(24px);
|
backdrop-filter: blur(24px);
|
||||||
@@ -93,9 +92,7 @@ import socials from "../data/socials.json";
|
|||||||
.social-link {
|
.social-link {
|
||||||
color: rgb(var(--accent-base));
|
color: rgb(var(--accent-base));
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
height: 2rem;
|
margin: 0 0.5rem;
|
||||||
line-height: 1;
|
|
||||||
margin: 0.25rem 0.5rem;
|
|
||||||
filter: drop-shadow(0px 0px 5px transparent);
|
filter: drop-shadow(0px 0px 5px transparent);
|
||||||
transition: filter 0.5s ease;
|
transition: filter 0.5s ease;
|
||||||
}
|
}
|
||||||
@@ -119,19 +116,10 @@ import socials from "../data/socials.json";
|
|||||||
max-width: 1000px;
|
max-width: 1000px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 800px) {
|
||||||
.landing-wrapper {
|
|
||||||
padding: 0;
|
|
||||||
margin-top: -1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bento-grid {
|
.bento-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-section {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bento-card {
|
.bento-card {
|
||||||
@@ -189,57 +177,21 @@ import socials from "../data/socials.json";
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.portfolio {
|
.portfolio { background: linear-gradient(135deg, rgba(var(--accent-base--portfolio), 0.5) 0%, rgba(var(--accent-base--portfolio), 0.15) 100%); }
|
||||||
background: linear-gradient(
|
.blog { background: linear-gradient(135deg, rgba(var(--accent-base--blog), 0.8) 0%, rgba(var(--accent-base--blog), 0.15) 100%); }
|
||||||
135deg,
|
.book { background: linear-gradient(135deg, rgba(var(--accent-base--book), 0.8) 0%, rgba(var(--accent-base--book), 0.15) 100%); }
|
||||||
rgba(var(--accent-base--portfolio), 0.5) 0%,
|
|
||||||
rgba(var(--accent-base--portfolio), 0.15) 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.blog {
|
|
||||||
background: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
rgba(var(--accent-base--blog), 0.8) 0%,
|
|
||||||
rgba(var(--accent-base--blog), 0.15) 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.book {
|
|
||||||
background: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
rgba(var(--accent-base--book), 0.8) 0%,
|
|
||||||
rgba(var(--accent-base--book), 0.15) 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.portfolio:hover {
|
.portfolio:hover { box-shadow: 0 10px 40px -10px rgba(var(--accent-base--portfolio), 1); }
|
||||||
box-shadow: 0 10px 40px -10px rgba(var(--accent-base--portfolio), 1);
|
.blog:hover { box-shadow: 0 10px 40px -10px rgba(var(--accent-base--blog), 0.4); }
|
||||||
}
|
.book:hover { box-shadow: 0 10px 40px -10px rgba(var(--accent-base--book), 0.4); }
|
||||||
.blog:hover {
|
|
||||||
box-shadow: 0 10px 40px -10px rgba(var(--accent-base--blog), 0.4);
|
|
||||||
}
|
|
||||||
.book:hover {
|
|
||||||
box-shadow: 0 10px 40px -10px rgba(var(--accent-base--book), 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.portfolio .icon {
|
.portfolio .icon { color: rgb(var(--accent-base--portfolio)); }
|
||||||
color: rgb(var(--accent-base--portfolio));
|
.blog .icon { color: rgb(var(--accent-base--blog)); }
|
||||||
}
|
.book .icon { color: rgb(var(--accent-base--book)); }
|
||||||
.blog .icon {
|
|
||||||
color: rgb(var(--accent-base--blog));
|
|
||||||
}
|
|
||||||
.book .icon {
|
|
||||||
color: rgb(var(--accent-base--book));
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeUp {
|
@keyframes fadeUp {
|
||||||
from {
|
from { opacity: 0; transform: translateY(30px); }
|
||||||
opacity: 0;
|
to { opacity: 1; transform: translateY(0); }
|
||||||
transform: translateY(30px);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.reveal-text {
|
.reveal-text {
|
||||||
@@ -257,20 +209,12 @@ import socials from "../data/socials.json";
|
|||||||
animation: fadeUp 0.8s ease-out forwards;
|
animation: fadeUp 0.8s ease-out forwards;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
.portfolio {
|
.portfolio { animation-delay: 0.4s; }
|
||||||
animation-delay: 0.4s;
|
.blog { animation-delay: 0.6s; }
|
||||||
}
|
.book { animation-delay: 0.8s; }
|
||||||
.blog {
|
|
||||||
animation-delay: 0.6s;
|
|
||||||
}
|
|
||||||
.book {
|
|
||||||
animation-delay: 0.8s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.bento-card,
|
.bento-card, .fade-in-up, .reveal-text {
|
||||||
.fade-in-up,
|
|
||||||
.reveal-text {
|
|
||||||
animation: none;
|
animation: none;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: none;
|
transform: none;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
import { getCollection, render } from 'astro:content';
|
import { getCollection, render } from 'astro:content';
|
||||||
import { Icon } from "astro-icon/components";
|
|
||||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||||
import "katex/dist/katex.min.css";
|
import "katex/dist/katex.min.css";
|
||||||
import "rehype-callouts/theme/obsidian"
|
import "rehype-callouts/theme/obsidian"
|
||||||
@@ -16,27 +15,15 @@ const { entry } = Astro.props;
|
|||||||
const { Content } = await render(entry);
|
const { Content } = await render(entry);
|
||||||
---
|
---
|
||||||
<BaseLayout title={entry.data.title} theme="portfolio">
|
<BaseLayout title={entry.data.title} theme="portfolio">
|
||||||
<div class="glass-container header" style={`view-transition-name: project-header-${entry.id};`}>
|
<div class="glass-container header">
|
||||||
<h1 style={`view-transition-name: project-headline-${entry.id};`}>{entry.data.title}</h1>
|
<h1>{entry.data.title}</h1>
|
||||||
<p>{entry.data.summary}</p>
|
<p>{entry.data.summary}</p>
|
||||||
{(entry.data.tags || entry.data.repository) &&
|
|
||||||
(<div class="additional-meta">
|
|
||||||
<div class="meta-tags">
|
|
||||||
{entry.data.tags && (
|
{entry.data.tags && (
|
||||||
<div class="tags">
|
<div class="tags">
|
||||||
{entry.data.tags?.map(tech => <span class="tag">{tech}</span>)}
|
{entry.data.tags.map(tech => <span class="tag">{tech}</span>)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div class="meta-repository">
|
|
||||||
{ entry.data.repository && (
|
|
||||||
<a href={entry.data.repository} referrerpolicy="no-referrer">
|
|
||||||
<Icon name="simple-icons:git" style={`view-transition-name: project-git-${entry.id};`} />
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="glass-container content prose">
|
<div class="glass-container content prose">
|
||||||
<Content />
|
<Content />
|
||||||
@@ -52,7 +39,6 @@ const { Content } = await render(entry);
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
.tag {
|
.tag {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
@@ -63,23 +49,4 @@ const { Content } = await render(entry);
|
|||||||
.content {
|
.content {
|
||||||
line-height: 1.8;
|
line-height: 1.8;
|
||||||
}
|
}
|
||||||
.additional-meta {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
gap: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-top: 1rem;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.meta-repository {
|
|
||||||
flex-shrink: 1;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: rgb(var(--accent-base));
|
|
||||||
}
|
|
||||||
.meta-repository a {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,37 +1,26 @@
|
|||||||
---
|
---
|
||||||
import { getCollection } from 'astro:content';
|
import { getCollection } from 'astro:content';
|
||||||
import { Icon } from "astro-icon/components";
|
|
||||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||||
|
|
||||||
const projects = await getCollection('portfolio');
|
const projects = await getCollection('portfolio');
|
||||||
projects.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
|
projects.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
|
||||||
---
|
---
|
||||||
<BaseLayout title="Portfolio" theme="portfolio" description="Eine Auswahl aktueller Projekte und Experimente von c0ntroller.de.">
|
<BaseLayout title="Portfolio" theme="portfolio" description="Eine Auswahl aktueller Projekte und Experimente von c0ntroller.de.">
|
||||||
<div class="glass-container" style="view-transition-name:main-glass;">
|
<div class="glass-container">
|
||||||
<h1>Meine Arbeiten</h1>
|
<h1>Meine Arbeiten</h1>
|
||||||
<p>Eine Auswahl aktueller Projekte und Experimente.</p>
|
<p>Eine Auswahl aktueller Projekte und Experimente.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
{projects.map(project => (
|
{projects.map(project => (
|
||||||
<a href={`/portfolio/${project.id}`} class="glass-container link-card" style={`view-transition-name: project-header-${project.id};`}>
|
<a href={`/portfolio/${project.id}`} class="glass-container link-card">
|
||||||
<h2 style={`view-transition-name: project-headline-${project.id};`}>{project.data.title}</h2>
|
<h2>{project.data.title}</h2>
|
||||||
<p>{project.data.summary}</p>
|
<p>{project.data.summary}</p>
|
||||||
{(project.data.tags || project.data.repository) &&
|
|
||||||
(<div class="additional-meta">
|
|
||||||
<div class="meta-tags">
|
|
||||||
{project.data.tags && (
|
{project.data.tags && (
|
||||||
<div class="tags">
|
<div class="tags">
|
||||||
{project.data.tags?.map(tech => <span class="tag">{tech}</span>)}
|
{project.data.tags?.map(tech => <span class="tag">{tech}</span>)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
<div class="meta-repository">
|
|
||||||
{ project.data.repository && (
|
|
||||||
<Icon name="simple-icons:git" style={`view-transition-name: project-git-${project.id};`} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>)}
|
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -51,22 +40,11 @@ projects.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
|
|||||||
.link-card h2 {
|
.link-card h2 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
.additional-meta {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
gap: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-top: 1rem;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.tags {
|
.tags {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
margin-top: 1rem;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
flex-grow: 1;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
.tag {
|
.tag {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
@@ -74,11 +52,4 @@ projects.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
|
|||||||
padding: 0.25rem 0.5rem;
|
padding: 0.25rem 0.5rem;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
.meta-repository {
|
|
||||||
flex-shrink: 1;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
color: rgb(var(--accent-base));
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
22
src/remark-modified-time.mjs
Normal file
22
src/remark-modified-time.mjs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { execSync } from "child_process";
|
||||||
|
import { statSync } from "fs";
|
||||||
|
|
||||||
|
export function remarkModifiedTime() {
|
||||||
|
return function (tree, file) {
|
||||||
|
const filepath = file.history[0];
|
||||||
|
try {
|
||||||
|
const result = execSync(`git log -1 --pretty="format:%cI" "${filepath}"`);
|
||||||
|
// If result is empty or undefined, fallback to fs stat
|
||||||
|
if (!result || !result.toString().trim()) {
|
||||||
|
throw new Error("No git history");
|
||||||
|
}
|
||||||
|
file.data.astro.frontmatter.lastModified = result.toString();
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore, fallback to fs stat
|
||||||
|
const result = statSync(filepath);
|
||||||
|
file.data.astro.frontmatter.lastModified = result.mtime.toISOString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,15 +1,10 @@
|
|||||||
*,
|
*, *::before, *::after {
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
transition: color .4s ease, background-color .4s ease, border-color .4s ease, box-shadow .4s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
@view-transition {
|
@view-transition {
|
||||||
navigation: auto;
|
navigation: auto;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
::view-transition-group(root) {
|
::view-transition-group(root) {
|
||||||
background-color: var(--bg-color);
|
background-color: var(--bg-color);
|
||||||
@@ -20,79 +15,66 @@
|
|||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: 214, 134, 249;
|
initial-value: 214, 134, 249;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --bg-image {
|
@property --bg-image {
|
||||||
syntax: '<image>';
|
syntax: '<image>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: url('../assets/backgrounds/bubble.svg');
|
initial-value: url('../assets/backgrounds/bubble.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --bg-image-static {
|
@property --bg-image-static {
|
||||||
syntax: '<image>';
|
syntax: '<image>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: url('../assets/backgrounds/bubble-static.svg');
|
initial-value: url('../assets/backgrounds/bubble-static.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --glass-bg {
|
@property --glass-bg {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: rgba(20, 25, 35, 0.4);
|
initial-value: rgba(20, 25, 35, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --glass-border {
|
@property --glass-border {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: rgba(255, 255, 255, 0.08);
|
initial-value: rgba(255, 255, 255, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --glass-blur {
|
@property --glass-blur {
|
||||||
syntax: '<length>';
|
syntax: '<length>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: 16px;
|
initial-value: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --glass-shadow {
|
@property --glass-shadow {
|
||||||
syntax: '<shadow>';
|
syntax: '<shadow>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
|
initial-value: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --text-main {
|
@property --text-main {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: #e0e7f0;
|
initial-value: #e0e7f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --text-muted {
|
@property --text-muted {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: #92a1b6;
|
initial-value: #92a1b6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --bg-color {
|
@property --bg-color {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: #0d0117;
|
initial-value: #0d0117;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --accent-base--default {
|
@property --accent-base--default {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: 214, 134, 249;
|
initial-value: 214, 134, 249;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --accent-base--portfolio {
|
@property --accent-base--portfolio {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: 255, 181, 102;
|
initial-value: 255, 181, 102;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --accent-base--blog {
|
@property --accent-base--blog {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
initial-value: 111, 221, 246;
|
initial-value: 111, 221, 246;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --accent-base--book {
|
@property --accent-base--book {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: true;
|
inherits: true;
|
||||||
@@ -140,25 +122,6 @@ body[data-theme="book"] {
|
|||||||
--bg-image-static: url('../assets/backgrounds/curve-ripple-static.svg');
|
--bg-image-static: url('../assets/backgrounds/curve-ripple-static.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
body:has(nav a[href="/"]:hover) {
|
|
||||||
--accent-base: var(--accent-base--default);
|
|
||||||
}
|
|
||||||
|
|
||||||
body:has(nav a[href="/portfolio"]:hover),
|
|
||||||
body:has(.portfolio:hover) {
|
|
||||||
--accent-base: var(--accent-base--portfolio);
|
|
||||||
}
|
|
||||||
|
|
||||||
body:has(nav a[href="/blog"]:hover),
|
|
||||||
body:has(.blog:hover) {
|
|
||||||
--accent-base: var(--accent-base--blog);
|
|
||||||
}
|
|
||||||
|
|
||||||
body:has(nav a[href="/book"]:hover),
|
|
||||||
body:has(.book:hover) {
|
|
||||||
--accent-base: var(--accent-base--book);
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background-color: var(--bg-color);
|
background-color: var(--bg-color);
|
||||||
}
|
}
|
||||||
@@ -184,12 +147,7 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h1,
|
h1, h2, h3, h4, h5, h6 {
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
color: rgb(var(--accent-base));
|
color: rgb(var(--accent-base));
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
@@ -251,24 +209,13 @@ a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mobile Responsiveness */
|
/* Mobile Responsiveness */
|
||||||
@media (max-width: 500px) {
|
@media (max-width: 600px) {
|
||||||
.container {
|
.container {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glass-container {
|
.glass-container {
|
||||||
padding: 1.25rem;
|
padding: 1.25rem;
|
||||||
}
|
}
|
||||||
|
h1 { font-size: 1.75rem; }
|
||||||
h1 {
|
h2 { font-size: 1.5rem; }
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user