first commit

This commit is contained in:
2026-05-19 11:03:31 +02:00
commit 08c65a4a19
21 changed files with 757 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
# Build and Release Folders
bin/
bin-debug/
bin-release/
[Oo]bj/ # FlashDevelop obj
[Bb]in/ # FlashDevelop bin
# Other files and folders
.settings/
# lock
*.lock
# Executables
*.swf
*.air
*.ipa
*.apk
# Hugo
public/
# Backup Files
*.markdown~
*.md~
# Apache
.htpasswd
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Build directories
public
dist
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
package-lock.json
bower_components
# Mac File System File...utterly useless to anyone but me.
.DS_Store
# AWS stuff for publishing static files
.aws-credentials.json
.awspublish*
notizen.md
+31
View File
@@ -0,0 +1,31 @@
# Homelab Blog
Moderne Hugo-Website im Terminal-Design für Homelab-Dokumentation, Services und Konfigurationen.
## Struktur
- `content/posts/` — Blogartikel
- `content/services/` — Service-Dokumentationen
- `content/configs/` — Konfigurationssnippets
- `content/projects/` — Infrastruktur- und Automatisierungsprojekte
- `layouts/` — eigene Templates
- `static/css/styles.css` — modernes Terminal-Theme
## Lokales Testen
1. Hugo installieren: https://gohugo.io/getting-started/installing/
2. In das Projektverzeichnis wechseln:
```bash
cd c:\Users\Lucas Hahmann\Documents\Code\homelab-blog
```
3. Lokalen Server starten:
```bash
hugo server -D
```
4. Im Browser öffnen: `http://localhost:1313`
## Anpassen
- `config.toml` für Titel, Menü und Farben
- `static/css/styles.css` für das Styling
- `content/*` für Inhalte und neue Seiten
+9
View File
@@ -0,0 +1,9 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
summary: "Kurze Zusammenfassung des Artikels."
categories: ["homelab"]
---
Einsteigertext hier.
+41
View File
@@ -0,0 +1,41 @@
baseURL = "https://example.com/"
languageCode = "de-de"
title = "Rackaris - Blog"
description = "Homelab-Dokumentation, Services, Konfigurationen und Insights in modernem Terminal-Look."
[params]
author = "Lucas Hahmann"
theme = "terminal"
subtitle = "Homelab, Tüfteln und Halbwissen"
showLastModified = true
[params.menu]
[[menu.main]]
name = "Home"
url = "/"
weight = 10
[[menu.main]]
name = "Blog"
url = "/posts/"
weight = 20
[[menu.main]]
name = "Services"
url = "/services/"
weight = 30
[[menu.main]]
name = "Configs"
url = "/configs/"
weight = 40
[[menu.main]]
name = "Projekte"
url = "/projects/"
weight = 50
[params.colors]
background = "#02040b"
panel = "#09101b"
border = "#164a76"
text = "#e6edf3"
accent = "#58d8ff"
danger = "#ff5a5f"
muted = "#7d9bb1"
+16
View File
@@ -0,0 +1,16 @@
---
title: "Homelab Blog"
date: 2026-05-10
draft: false
---
Welcome to my Homelab blog. Hier dokumentiere ich meine Services, Configs und Projekte in einem klaren, textlastigen Tech-Format.
## Struktur
- `Blog`: Artikel zu homelab-relevanten Themen
- `Services`: laufende Dienste, Setup und Betrieb
- `Configs`: Konfigurationsbeispiele, Optimierungen und Hardening
- `Projekte`: Infrastruktur, Automatisierung und Deployment
Bleib dran für neue Beiträge und nützliche Snippets.
+7
View File
@@ -0,0 +1,7 @@
---
title: "Configs"
description: "Konfigurationen, Snippets und Best Practices für dein Homelab."
draft: false
---
Sichere und reproduzierbare Konfigurationsbeispiele für Netzwerk, SSH, Services und mehr.
+30
View File
@@ -0,0 +1,30 @@
---
title: "Impressum"
date: 2023-11-18T10:00:00+01:00
layout: page
url: "/impressum/"
---
Lucas Hahmann
Postfach 2002
Güterstr. 56
54295 Trier
E-Mail: info@hahmann-trier.de
## Disclaimer rechtliche Hinweise
### § 1 Warnhinweis zu Inhalten
Die kostenlosen und frei zugänglichen Inhalte dieser Webseite wurden mit größtmöglicher Sorgfalt erstellt. Der Anbieter dieser Webseite übernimmt jedoch keine Gewähr für die Richtigkeit und Aktualität der bereitgestellten kostenlosen und frei zugänglichen journalistischen Ratgeber und Nachrichten. Namentlich gekennzeichnete Beiträge geben die Meinung des jeweiligen Autors und nicht immer die Meinung des Anbieters wieder. Allein durch den Aufruf der kostenlosen und frei zugänglichen Inhalte kommt keinerlei Vertragsverhältnis zwischen dem Nutzer und dem Anbieter zustande, insoweit fehlt es am Rechtsbindungswillen des Anbieters.
### § 2 Externe Links
Diese Website enthält Verknüpfungen zu Websites Dritter ("externe Links"). Diese Websites unterliegen der Haftung der jeweiligen Betreiber. Der Anbieter hat bei der erstmaligen Verknüpfung der externen Links die fremden Inhalte daraufhin überprüft, ob etwaige Rechtsverstöße bestehen. Zu dem Zeitpunkt waren keine Rechtsverstöße ersichtlich. Der Anbieter hat keinerlei Einfluss auf die aktuelle und zukünftige Gestaltung und auf die Inhalte der verknüpften Seiten. Das Setzen von externen Links bedeutet nicht, dass sich der Anbieter die hinter dem Verweis oder Link liegenden Inhalte zu Eigen macht. Eine ständige Kontrolle der externen Links ist für den Anbieter ohne konkrete Hinweise auf Rechtsverstöße nicht zumutbar. Bei Kenntnis von Rechtsverstößen werden jedoch derartige externe Links unverzüglich gelöscht.
### § 3 Urheber- und Leistungsschutzrechte
Die auf dieser Website veröffentlichten Inhalte unterliegen dem deutschen Urheber- und Leistungsschutzrecht. Jede vom deutschen Urheber- und Leistungsschutzrecht nicht zugelassene Verwertung bedarf der vorherigen schriftlichen Zustimmung des Anbieters oder jeweiligen Rechteinhabers. Dies gilt insbesondere für Vervielfältigung, Bearbeitung, Übersetzung, Einspeicherung, Verarbeitung bzw. Wiedergabe von Inhalten in Datenbanken oder anderen elektronischen Medien und Systemen. Inhalte und Rechte Dritter sind dabei als solche gekennzeichnet. Die unerlaubte Vervielfältigung oder Weitergabe einzelner Inhalte oder kompletter Seiten ist nicht gestattet und strafbar. Lediglich die Herstellung von Kopien und Downloads für den persönlichen, privaten und nicht kommerziellen Gebrauch ist erlaubt.
Die Darstellung dieser Website in fremden Frames ist nur mit schriftlicher Erlaubnis zulässig.
### § 4 Besondere Nutzungsbedingungen
Soweit besondere Bedingungen für einzelne Nutzungen dieser Website von den vorgenannten Paragraphen abweichen, wird an entsprechender Stelle ausdrücklich darauf hingewiesen. In diesem Falle gelten im jeweiligen Einzelfall die besonderen Nutzungsbedingungen.
+43
View File
@@ -0,0 +1,43 @@
---
title: "Willkommen bei Rackaris"
date: 2026-05-11
draft: false
summary: "Was habe ich vor?"
---
Hallo zusammen,
Willkommen auf **Rackaris**, meinem Blog zum Thema Homelabbing.
Kurze Worte zu mir: Ich habe 2019 mit der Lehre als Fachinformatiker für Systemintegration angefangen und sie 2022 erfolgreich abgeschlossen. Seitdem arbeite ich als IT-Systemadministrator und habe viele Projekte angefangen, aber nur wenige zu Ende gebracht. Natürlich habe ich auch angefangen und mein Homelab damals aufgebaut. Dieses wurde sehr groß und viele verschiedene Services laufen darüber. Leider hat mir aber sehr die Erfahrung am Anfang gefehlt, weswegen ich "komische" Entscheidungen getroffen habe, wie ich etwas aufgebaut und installiert habe. Zudem habe ich auf eine Dokumentation verzichtet, was sich als komplettes Chaos entpuppt hat. Ich habe halt als Azubi angefangen und das *Monster* laufen lassen.
Vor etwa 3 Monaten ist dann der **WORST CASE** eingetreten und mein Home-Server hat den Geist aufgegeben. Zwei Festplatten hatten einen Defekt und konnten viele Sektoren nicht mehr lesen. Manche VMs konnte ich noch retten (aber die meisten sind wegen keiner Datensicherung verloren gegangen). Mein Homeserver war eh nie der beste (mein alter Gaming PC):
- I5 - 6600K
- 32GB RAM DDR4
- HDDs überall
Ich habe den Entschluss gefasst und gesagt: „Ich muss alles neu machen, diesmal richtig und mit der angewandten Berufserfahrung, die ich über die Jahre gesammelt habe". Ich habe richtig Lust bekommen, einen neuen Server zu kaufen und richtig durchzustarten mit ordentlicher Struktur. Zudem wollte ich auch richtig Power mit dem neuen Server haben und upgraden.
Dann habe ich die Hardwarepreise gesehen und habe angefangen zu weinen: 64 GB DDR5RAM für schlappe 800 €? 8TBHDD für 300 €? NVMeSSDs, die ich vor ein paar Jahren für 100€ gekauft habe, kosten jetzt 250€?
Es ist einfach unbezahlbar für eine Privatperson geworden, die nicht gleich über 3.000€ ausgeben wollte. Zudem wollte ich nicht richtig Abstriche machen, weil das mir später eh wieder ins Bein schießt. Ich habe etwas recherchiert und hatte noch im Hinterkopf die Hetzner Serverbörse, wo ein Kumpel seinen Server laufen gelassen hat. Nach langem Hin-und-Her-Rechnen und verschiedenen Hardwarekonstellationen habe ich mich dazu entschieden, einfach einen Server aus der Serverbörse zu nehmen. Es war am einfachsten in der jetzigen Zeit und tatsächlich am günstigsten (für einen gewissen Zeitraum).
Ich habe nun folgenden Server gemietet:
- i7-8700
- 64 GB RAM DDR4
- 3x 1 TB NVME
Der Server kostet mich etwa 72€ pro Monat + eine Failover-IP-Adresse für 5€ pro Monat. Das Beste ist es nicht, aber für meine Bedürfnisse im Homelabbing reicht es aus. Ich habe mir natürlich auch einen Plan gemacht, wie ich den Server aufziehe, und wollte ziemlich eskalieren damit:
- Proxmox als Hypervisor
- OpenSense als Firewall
- VLANs
- Clients
- Alles auf einem System laufen haben (habe bei netcup und 1blu noch so paar Sachen …).
Ich möchte nahezu komplett autark werden mit allem. Zudem alles von Grund auf neu bauen und in einem Wiki dokumentieren. Diesen Blog hier mache ich als eine Art Changelog und weil ich einfach Bock habe, ein wenig zu schreiben. Also wenn ihr Lust habt (hoffe, irgendeiner liest das), könnt ihr den Aufbau und die Konfiguration verfolgen.
Machts gut
Lucas
@@ -0,0 +1,87 @@
---
title: "Proxmox Installation bei Hetzner"
date: 2026-05-11
draft: true
summary: "Wie bin ich vorgegangen und welche Schwiereigkeiten hatte ich"
---
Hallo zusammen,
um ehrlich zu sein, ich habe mir die Proxmox Installation bei Hetzner einfacher vorgestellt. Ich habe mich jedoch auch vorher nicht informiert und habe einfach dies so angenommen. Nach der Bestellung von meinem Serverbörse Server war dieser sehr schnell bereitgestellt und ich konnte anfangen.
## Try and Error
Ich habe mich an die Anleitung von Hetzner gehalten ([Hetzner Dokumentation](https://community.hetzner.com/tutorials/install-and-configure-proxmox_ve "Hetzner Dokumentation")). Diese schlagen zuerst vor, mann solle ein Blanko Debain 13 installieren und danach Proxmox nachinstallieren. Beschirben wird die Installation via dem *installimage* Script welches bei mir nicht funktioniert hat. Die Installation lief durch, ich hatte jedoch keine **Boot-Partition** und der Server ist ins leere gelaufen. Nach ein paar mal versuchen habe ich auch unter *Others* > *Proxmox* entdeckt und diese Installation versucht, mit dem selben Ergebnis. Über die Weboberfläche konnte man auch eine Debian 13 Installation starten, diese hat aber so komische RAIDs angelegt, dass ich diese Config so nicht nutzen konnte.
Ich habe noch versucht die Boot Partition manuell anzulegen und via chroot GRUB neuzuinstallieren, leider ohne Erfolg. Ich habe also den zweiten weg versucht.
## Installation via QEMU
Bei der Hetzner Dokumentation stand noch eine weitere Vorgehensweise, man lädt sich das Proxmox ISO runter und startet eine virtuelle Maschine via QEMU. Die Festplatte wird als Passthrough durcggeben und die VM installiert dabei direkt auf die Festplatte, die man später booten kann. Zudem tunnelt man sich eine VNC Verbindung auf den lokalen PC um den Installationsassistenten sehen zu können. Zuerst kam mir das sehr wild vor, aber es hat geklappt:
```bash
1. In Resuce System booten
2. SSH Tunnel aufbauen
ssh -L 5900:localhost:5900 root@23.88.69.115
3. Proxmox ISO herunterladen
wget https://enterprise.proxmox.com/iso/proxmox-ve_9.1-1.iso # Das neuste beachten!
4. Heruasfinden ob Legacy oder UEFI
[ -d "/sys/firmware/efi" ] && echo "UEFI" || echo "BIOS"
Bei mir war Legacy, deswegen brauchte ich nicht '-bios /usr/share/OVMF/OVMF_CODE.fd \' bei der VM
5. QEMU starten
qemu-system-x86_64 \
-enable-kvm \
-cpu host \
-m 16G \
-boot d \
-cdrom ./proxmox-ve_9.1-1.iso \
-drive file=/dev/nvme0n1,format=raw,if=virtio \
-vnc 127.0.0.1:0
! Richtige Festplatte durchgeben !
6. Über den VNC Viewer verbinden mit localhost und die Installation starten
7. Bei mir kam nach der erstInstallation ein Fehler, dass die vda3 Platte nicht gefunden werden konnte. Ich habe die Installation im selben Fenster nochmal neugestartet und es ging.
Ich konnte kein @ Zeichen schreiben via VNC Console, deswegen musste ich das @ Zeichen bei der Mail behalten ;D
8. Die VM kann einfach durch CTRL+C beendet werden auf der Shell, wir müssen noch was im Netzwerk konfigurieren.
9. Im Rescue System **predict-check** ausführen und schauen wir die Netzwerkschnittstelle heißt (bei mir eno1).
10. VM wieder starten und anmelden über VNC + in Proxmox anmelden.
qemu-system-x86_64 \
-enable-kvm \
-cpu host \
-m 16G \
-boot d \
-drive file=/dev/nvme0n1,format=raw,if=virtio \
-vnc 127.0.0.1:0
11. In der Datei /etc/network/interfaces muss das wirkliche Interface Name eingetragen werden + IP
Beispiel:
auto lo
iface lo inet loopback
auto en01
iface eno1 inet static
address your_server_ip/32
gateway your_server_gateway
12. Rebooten und Proxmox ist bei mir gelaufen
```
## Hoffentlich läuft jetzt Proxmox
Die Web Oberfläche sollte nun erreichbar sein (Port 8006), aber man muss sich vergewissern, dass dies sehr anfällig für jegliche Attacken ist. Ich habe meinen Proxmox danach noch gut abgesichert und werde es in Zukunft noch weiter machen, aber die Grundinstallation ist fertig.
Grüße
Lucas
+7
View File
@@ -0,0 +1,7 @@
---
title: "Blog"
description: "Technische Artikel und Guides für dein Homelab."
draft: false
---
Hier findest du Artikel zu Homelab-Themen, Automatisierung und Infrastruktur.
+7
View File
@@ -0,0 +1,7 @@
---
title: "Projekte"
description: "Infrastrukturprojekte, Automatisierung und Lab-Experimente."
draft: false
---
Projekt-Dokumentationen für Homelab-Architektur, Storage und DevOps-Workflows.
+7
View File
@@ -0,0 +1,7 @@
---
title: "Services"
description: "Dokumentation laufender Homelab-Services, Deployments und Monitoring."
draft: false
---
Service-Dokumentationen mit Konfigurationen, Abhängigkeiten und Betriebshinweisen.
+15
View File
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="de">
<head>
{{ partial "head.html" . }}
</head>
<body>
<div class="site-shell">
{{ partial "header.html" . }}
<main class="site-main" role="main">
{{ block "main" . }}{{ end }}
</main>
{{ partial "footer.html" . }}
</div>
</body>
</html>
+21
View File
@@ -0,0 +1,21 @@
{{ define "main" }}
<section class="content-panel">
<div class="panel-header">
<h2>{{ .Title }}</h2>
{{ with .Description }}
<p class="panel-description">{{ . }}</p>
{{ end }}
</div>
<div class="post-grid">
{{ range .Pages }}
<article class="post-card">
<a href="{{ .RelPermalink }}">
<p class="card-meta">{{ .Date.Format "02.01.2006" }}</p>
<h3>{{ .Title }}</h3>
<p>{{ .Summary }}</p>
</a>
</article>
{{ end }}
</div>
</section>
{{ end }}
+12
View File
@@ -0,0 +1,12 @@
{{ define "main" }}
<article class="content-panel post-detail">
<div class="panel-header detail-header">
<p class="card-meta">{{ .Date.Format "02.01.2006" }}</p>
<h1>{{ .Title }}</h1>
{{ with .Params.summary }}
<p class="panel-description">{{ . }}</p>
{{ end }}
</div>
<div class="post-body">{{ .Content }}</div>
</article>
{{ end }}
View File
+43
View File
@@ -0,0 +1,43 @@
{{ define "main" }}
<section class="hero-panel">
<div>
<p class="eyebrow">HOMELAB Docs</p>
<h2>Dokumentation, Anleitungen und meinen Senf</h2>
<p>
Hier findest du meine gesammelten Dokumentationen, Anleitungen und Erfahrungen rund um mein Homelab. Von technischen Artikeln über Service-Dokus bis hin zu Konfigurationen und Projekten alles, was ich spannend finde, teile ich hier mit dir.
</p>
</div>
<div class="hero-code">
<pre><code>$ tree -L 2
.
├── posts/
├── services/
├── configs/
└── projects/
</code></pre>
</div>
</section>
<section class="content-panel overview-grid">
<article class="overview-card">
<h3>Blog</h3>
<p>Technische Artikel, Insights und How-Tos.</p>
<a class="button" href="/posts/">Ansehen</a>
</article>
<article class="overview-card">
<h3>Services</h3>
<p>Service-Dokus, Deployments und Monitoring.</p>
<a class="button" href="/services/">Ansehen</a>
</article>
<article class="overview-card">
<h3>Configs</h3>
<p>Konfigurationen, Best Practices und Snippets.</p>
<a class="button" href="/configs/">Ansehen</a>
</article>
<article class="overview-card">
<h3>Projekte</h3>
<p>Infra-Setups, Automatisierung und Experimente.</p>
<a class="button" href="/projects/">Ansehen</a>
</article>
</section>
{{ end }}
+9
View File
@@ -0,0 +1,9 @@
<footer class="site-footer">
<div>
<p>
© {{ now.Format "2006" }} Rackaris Blog — Dokumentation &amp;
Konfiguration
</p>
<a href="/impressum/" class="nav-link">Impressum</a>
</div>
</footer>
+14
View File
@@ -0,0 +1,14 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ if .Title }}{{ .Title }} | {{ end }}{{ .Site.Title }}</title>
<meta
name="description"
content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.subtitle }}{{ end }}"
/>
<link rel="stylesheet" href="/css/styles.css" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&display=swap"
rel="stylesheet"
/>
+14
View File
@@ -0,0 +1,14 @@
<header class="site-header">
<div class="header-inner">
<div>
<p class="eyebrow">Wilkommen zu</p>
<h1>{{ .Site.Title }}</h1>
<p class="subtitle">{{ .Site.Params.subtitle }}</p>
</div>
<nav class="site-nav" aria-label="Hauptnavigation">
{{ range .Site.Menus.main }}
<a href="{{ .URL }}" class="nav-link">{{ .Name }}</a>
{{ end }}
</nav>
</div>
</header>
+272
View File
@@ -0,0 +1,272 @@
:root {
color-scheme: dark;
--bg: #02040b;
--panel: #09101b;
--border: #164a76;
--text: #e6edf3;
--muted: #7d9bb1;
--accent: #58d8ff;
--accent-soft: rgba(88, 216, 255, 0.16);
--danger: #ff5a5f;
--radius: 20px;
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
min-height: 100%;
background:
radial-gradient(
circle at top,
rgba(88, 216, 255, 0.08),
transparent 35%
),
linear-gradient(180deg, #02040b 0%, #050915 100%);
color: var(--text);
font-family: "Fira Code", Consolas, "Courier New", monospace;
line-height: 1.6;
}
body {
padding: 0;
}
a {
color: var(--accent);
text-decoration: none;
}
a:hover,
a:focus {
color: #bae9ff;
}
.site-shell {
max-width: 1200px;
margin: 0 auto;
padding: 24px;
}
.site-header {
padding: 28px 20px;
border: 1px solid rgba(88, 216, 255, 0.12);
border-radius: var(--radius);
background: rgba(6, 13, 22, 0.85);
backdrop-filter: blur(12px);
margin-bottom: 24px;
}
.header-inner {
display: grid;
gap: 20px;
}
.eyebrow {
margin: 0 0 10px;
color: var(--accent);
letter-spacing: 0.2em;
text-transform: uppercase;
font-size: 0.85rem;
}
.site-header h1 {
margin: 0;
font-size: clamp(2rem, 4vw, 3.6rem);
}
.subtitle {
margin: 14px 0 0;
color: var(--muted);
max-width: 700px;
}
.site-nav {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.nav-link {
display: inline-flex;
align-items: center;
padding: 12px 16px;
border-radius: 999px;
border: 1px solid rgba(88, 216, 255, 0.12);
background: rgba(255, 255, 255, 0.02);
transition:
background 0.2s ease,
border-color 0.2s ease;
}
.nav-link:hover {
background: rgba(88, 216, 255, 0.12);
border-color: rgba(88, 216, 255, 0.28);
}
.hero-panel,
.content-panel {
border: 1px solid rgba(255, 255, 255, 0.06);
background: rgba(8, 16, 28, 0.88);
border-radius: var(--radius);
padding: 28px;
margin-bottom: 24px;
}
.hero-panel {
display: grid;
grid-template-columns: 1.6fr 1fr;
gap: 24px;
align-items: center;
}
.hero-panel h2 {
margin-top: 0;
font-size: clamp(2.1rem, 3.5vw, 3.5rem);
}
.hero-panel p {
max-width: 640px;
}
.hero-code {
background: rgba(15, 23, 40, 0.95);
border: 1px solid rgba(88, 216, 255, 0.14);
border-radius: 18px;
overflow: hidden;
}
.hero-code pre {
margin: 0;
padding: 24px;
font-size: 0.92rem;
color: #a7d2ff;
}
.post-grid,
.overview-grid {
display: grid;
gap: 20px;
}
.post-grid {
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.overview-grid {
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.post-card,
.overview-card {
border: 1px solid rgba(88, 216, 255, 0.1);
border-radius: 18px;
padding: 24px;
background: rgba(10, 18, 32, 0.9);
transition:
transform 0.2s ease,
border-color 0.2s ease;
}
.post-card:hover,
.overview-card:hover {
transform: translateY(-4px);
border-color: rgba(88, 216, 255, 0.22);
}
.post-card h3,
.overview-card h3 {
margin: 8px 0 14px;
color: #f1f8ff;
}
.card-meta {
margin: 0 0 12px;
color: var(--accent);
font-size: 0.85rem;
}
.post-card p,
.overview-card p {
margin: 0;
color: var(--muted);
}
.post-detail {
max-width: 900px;
}
.detail-header {
margin-bottom: 24px;
}
.post-body {
padding-top: 8px;
color: var(--text);
}
.post-body h2,
.post-body h3,
.post-body h4 {
color: #ffffff;
}
.post-body code,
.post-body pre {
font-family: "Fira Code", Consolas, "Courier New", monospace;
}
.post-body pre {
background: rgba(4, 11, 20, 0.95);
padding: 18px;
border-radius: 16px;
overflow-x: auto;
border: 1px solid rgba(88, 216, 255, 0.14);
}
.post-body code {
background: rgba(88, 216, 255, 0.08);
padding: 3px 6px;
border-radius: 6px;
}
.button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 12px 18px;
margin-top: 20px;
background: var(--accent);
color: #02040b;
border-radius: 999px;
font-weight: 600;
}
.site-footer {
padding: 24px 20px;
text-align: center;
color: var(--muted);
}
@media (max-width: 840px) {
.hero-panel {
grid-template-columns: 1fr;
}
}
@media (max-width: 560px) {
.site-shell {
padding: 16px;
}
.site-nav {
justify-content: flex-start;
}
.button {
width: 100%;
}
}