Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 76 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,80 @@

Hi there 👋 You've found my personal website and blog.

Currently, it's built using:
Built with Hugo and plain CSS; served by Caddy.

- Next.JS
- TailwindCSS
- MDX via Remark
- Vercel
## Local development

Run `hugo server` and open `http://localhost:1313/`. Use `hugo` for a production build.

## Design system

All pages use the Pocket ID-inspired theme: locally hosted Instrument Serif for
the homepage name and main page titles, system sans-serif for section headings
and body text, neutral surfaces, rounded cards, and automatic light/dark modes.
No Tailwind or frontend build dependencies are needed.

- `assets/css/base.css` owns shared theme tokens, typography, navigation, and footer.
- `assets/css/main.css` owns the homepage, archives, articles, projects, and reference tables.
- `assets/css/finance.css` adds finance-specific layouts without redefining the shared theme.
- `layouts/partials/icon.html` contains the shared inline icons.

The editorial R in `static/icon.svg` is outlined from the site's Instrument Serif
typeface, with slightly strengthened strokes for small sizes. This vector master
has no runtime font dependency and is used in the personal-site header and as the
SVG favicon. Its colors adapt to light/dark preferences. PNG and ICO exports use
the fixed dark tile; the Apple touch icon is opaque for the platform's own mask.

Icon URLs carry the `v=2` revision to avoid stale browser caches. When replacing
the artwork, update that revision in the header, head links, and web manifest.

Regenerate the raster exports with ImageMagick:

```sh
magick -background none -density 1536 static/icon.svg -resize 1024x1024 \
-depth 8 -strip /tmp/riesinger-icon-master.png
for size in 16 32; do
magick /tmp/riesinger-icon-master.png -resize "${size}x${size}" "static/favicon-${size}x${size}.png"
done
for size in 192 512; do
magick /tmp/riesinger-icon-master.png -resize "${size}x${size}" "static/android-chrome-${size}x${size}.png"
done
magick /tmp/riesinger-icon-master.png -resize 180x180 -background '#171717' \
-alpha remove -alpha off static/apple-touch-icon.png
magick /tmp/riesinger-icon-master.png -define icon:auto-resize=48,32,16 static/favicon.ico
```

The main archive's tag filter is progressively enhanced: without JavaScript,
all entries remain visible. Wide reference pages use `wide: true` in frontmatter.

Same-origin navigation uses native CSS View Transitions from `base.css`, with a
steady header and a quick page fade by default. Writing, project, and investment
card titles marked `data-transition-title` move into the destination `main h1`
over 320ms; the remaining content then fades in over 180ms.

`assets/js/page-transitions.js` pairs only the selected title through the native
`pageswap` / `pagereveal` events. Its classic script deliberately loads in the
head before the first render; do not add `async`, `defer`, or `type="module"`.
It hands off an ephemeral source/destination URL pair through session storage,
consumes it on arrival, and clears temporary transition names when finished.
New card title markers must be inside their destination links.

Reduced-motion preferences disable all page transitions. Without JavaScript,
the required browser APIs, or session storage, navigation keeps the basic fade
where supported, otherwise ordinary page changes. No client-side router is used;
same-page anchors and opening links in a new tab retain their native behavior.

## Finance introduction

The German learning area starts at `/finance-intro/`. Its layouts live in
`layouts/finance-intro/` and use the same shared design system as the main site.
The finance area does not require JavaScript.

Content lives in `content/finance-intro/`. Each investment page defines its
`category` (`classic` or `market`), `weight`, `label`, `summary`, a short `benefit`
and `drawback` for the overview, and `benefits` / `drawbacks` lists for the detail
page. The overview and related-topic links are generated from these pages.

Keep explanations brief, cite authoritative sources, and link unfamiliar terms to
the explicit anchors in `glossar.md`. The glossary navigation is generated from
its headings.
138 changes: 138 additions & 0 deletions assets/css/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/* Shared Pocket ID-inspired typography, surfaces and site chrome. */
@font-face {
font-family: "Instrument Serif";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("/fonts/InstrumentSerif-Regular.woff2") format("woff2");
}

:root {
color-scheme: light dark;
--background: #ffffff;
--surface: #fafafa;
--soft: #f2f2f2;
--border: #e5e5e5;
--muted: #666666;
--ink: #171717;
--display: "Instrument Serif", Georgia, serif;
--body: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
:root {
--background: #111111;
--surface: #181818;
--soft: #242424;
--border: #333333;
--muted: #aaaaaa;
--ink: #f5f5f5;
}
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 2rem; -webkit-text-size-adjust: 100%; }
body { margin: 0; min-height: 100svh; display: flex; flex-direction: column; background: var(--background); color: var(--ink); font: 16px/1.6 var(--body); -webkit-font-smoothing: antialiased; }
body > main { flex: 1; }
a { color: inherit; text-underline-offset: .2em; }
svg { flex-shrink: 0; vertical-align: middle; }
img, video, audio { max-width: 100%; }
h1, h2, h3, h4, h5, h6, p { margin: 0; }
h1 { font: 400 clamp(42px, 5.3vw, 66px)/1.06 var(--display); letter-spacing: -.025em; text-wrap: balance; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 5px; }
[hidden] { display: none !important; }
.frame { width: min(1120px, calc(100% - 64px)); margin-inline: auto; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.skip-link { position: fixed; top: 12px; left: 12px; padding: 10px 20px; background: var(--ink); color: var(--background); border-radius: 24px; transform: translateY(-180%); z-index: 10; }
.skip-link:focus { transform: translateY(0); }
.site-header { min-height: 100px; display: flex; align-items: center; justify-content: space-between; gap: 24px; border-bottom: 1px solid var(--border); }
.brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; font-weight: 600; font-size: 15px; }
.brand-mark { display: grid; place-items: center; flex-shrink: 0; width: 38px; height: 38px; border-radius: 12px; background: var(--ink); color: var(--background); }
.brand-mark img { display: block; width: 100%; height: 100%; }
.site-header nav { display: flex; gap: 6px; font-size: 14px; }
.site-header nav a { display: block; padding: 8px 16px; text-decoration: none; border-radius: 24px; color: var(--muted); }
.site-header nav a[aria-current="page"] { background: var(--soft); color: var(--ink); }
.site-header nav a:hover { color: var(--ink); background: var(--surface); }
.eyebrow { display: block; margin-bottom: 14px; font-size: 12px; font-weight: 600; color: var(--muted); letter-spacing: .07em; text-transform: uppercase; }
.button { display: inline-flex; align-items: center; justify-content: center; gap: 14px; border-radius: 30px; background: var(--ink); color: var(--background); text-decoration: none; font-size: 14px; font-weight: 500; padding: 12px 20px; margin-top: 28px; }
.button:hover { opacity: .82; }
.back-link { display: inline-flex; align-items: center; gap: 8px; color: var(--muted); text-decoration: none; font-size: 13px; }
.back-link svg { width: 16px; height: 16px; }
.back-link:hover { color: var(--ink); }
.site-footer { display: flex; justify-content: space-between; align-items: center; gap: 24px; padding-block: 26px; border-top: 1px solid var(--border); margin-top: 64px; color: var(--muted); font-size: 12px; }
.site-footer a { white-space: nowrap; text-decoration: none; }
.site-footer a:hover { color: var(--ink); }
.site-footer svg { width: 13px; height: 13px; margin-left: 4px; }

@media (max-width: 760px) {
.frame { width: calc(100% - 40px); }
.site-header { min-height: 88px; gap: 12px; }
.brand { font-size: 13px; gap: 8px; }
.brand-mark { width: 32px; height: 32px; border-radius: 10px; }
.site-header nav { gap: 0; font-size: 12px; }
.site-header nav a { padding: 7px 10px; }
.site-footer { align-items: flex-start; }
}
@media (max-width: 480px) {
.frame { width: calc(100% - 32px); }
.site-footer { flex-direction: column; gap: 12px; margin-top: 48px; }
}
/* Native same-origin navigation: fade the page while keeping the header steady.
Root snapshots avoid scaling content between wide and narrow page layouts. */
@media (prefers-reduced-motion: no-preference) {
@view-transition { navigation: auto; }

body > .site-header { view-transition-name: site-header; }
::view-transition-group(root),
::view-transition-group(site-header) { animation: none; }
::view-transition-old(site-header) { display: none; }
::view-transition-new(site-header) { animation: none; }
::view-transition-old(root) {
animation: 140ms ease-out both page-out;
mix-blend-mode: normal;
}
::view-transition-new(root) {
animation: 180ms ease-out both page-in;
mix-blend-mode: normal;
}

/* A card title travels first; the rest of the destination follows it. */
::view-transition-group(page-title) {
animation-duration: 320ms;
animation-timing-function: cubic-bezier(.22, .61, .36, 1);
z-index: 1;
}
::view-transition-old(page-title) {
animation: 140ms ease-out both heading-out;
mix-blend-mode: normal;
}
::view-transition-new(page-title) {
animation: 320ms ease-out both heading-in;
mix-blend-mode: normal;
}
:root[data-heading-transition]::view-transition-new(root) {
animation-delay: 320ms;
}

@keyframes heading-out {
to { opacity: 0; }
}
@keyframes heading-in {
from { opacity: 0; }
to { opacity: 1; }
}

@keyframes page-out {
to { opacity: 0; transform: translateY(-4px); }
}
@keyframes page-in {
from { opacity: 0; transform: translateY(6px); }
to { opacity: 1; transform: translateY(0); }
}
}

@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
*, *::before, *::after { animation: none !important; transition: none !important; }
}
102 changes: 102 additions & 0 deletions assets/css/finance.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* Finance-specific cards and learning pages; shared styles live in base.css. */
.intro { max-width: 710px; padding-block: 68px 62px; }
.intro-copy { margin-top: 22px; max-width: 575px; font-size: 17px; color: var(--muted); }
.text-link { display: inline-block; margin: 16px 0 0 20px; color: var(--muted); font-size: 13px; }
.section-heading h2 { font-size: 18px; font-weight: 600; letter-spacing: -.02em; }
.section-heading p { color: var(--muted); font-size: 14px; margin-top: 4px; }
.basics-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 20px; }
.basic-card { display: flex; flex-direction: column; gap: 8px; padding: 20px; background: var(--surface); border: 1px solid var(--border); border-radius: 16px; text-decoration: none; }
.basic-card > span:last-child { font-size: 13px; line-height: 1.5; color: var(--muted); }
.basic-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 14px; font-weight: 600; }
.basic-title svg { width: 16px; height: 16px; }
.basic-card:hover { border-color: var(--muted); }
.investments { padding-top: 44px; }
.section-nav { display: flex; flex-wrap: wrap; gap: 8px; border-bottom: 1px solid var(--border); padding-bottom: 18px; }
.section-nav a { font-size: 13px; text-decoration: none; border-radius: 24px; padding: 8px 15px; background: var(--soft); }
.section-nav a:last-child { margin-left: auto; background: transparent; color: var(--muted); }
.section-nav svg { width: 14px; height: 14px; margin-left: 4px; }
.section-nav a:hover { box-shadow: inset 0 0 0 1px var(--border); }
.investment-section { padding-top: 36px; }
.investment-section + .investment-section { padding-top: 44px; }
.category-heading { display: flex; align-items: center; gap: 14px; }
.category-icon { display: grid; place-items: center; flex-shrink: 0; width: 44px; height: 44px; background: var(--soft); border-radius: 14px; }
.category-heading h2 { font: 600 26px/1.25 var(--body); letter-spacing: -.025em; }
.category-heading p { font-size: 13px; color: var(--muted); margin-top: 3px; }
.category-description { max-width: 740px; color: var(--muted); font-size: 14px; margin-top: 16px; }
.investment-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; margin-top: 22px; }
.investment-card { display: flex; flex-direction: column; min-width: 0; padding: 22px; border: 1px solid var(--border); border-radius: 18px; text-decoration: none; transition: border-color 150ms ease, background-color 150ms ease; }
.investment-card:hover { border-color: var(--muted); background: var(--surface); }
.card-heading { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 24px; }
.card-heading > svg { width: 17px; height: 17px; color: var(--muted); }
.tag { display: inline-block; width: fit-content; padding: 3px 9px; background: var(--soft); border-radius: 20px; color: var(--muted); font-size: 11px; line-height: 1.5; }
.investment-card h3 { font-size: 19px; font-weight: 600; line-height: 1.3; letter-spacing: -.025em; overflow-wrap: anywhere; }
.card-summary { color: var(--muted); font-size: 13px; line-height: 1.6; margin-top: 10px; min-height: 6.4em; }
.card-tradeoffs { display: grid; gap: 10px; border-top: 1px solid var(--border); padding-top: 16px; margin: 18px 0 22px; font-size: 12px; line-height: 1.5; }
.card-tradeoffs > div { display: flex; gap: 8px; }
.card-tradeoffs dt { display: flex; padding-top: 1px; }
.card-tradeoffs svg { width: 15px; height: 15px; }
.card-tradeoffs dd { margin: 0; color: var(--muted); }
.card-more { margin-top: auto; font-size: 12px; font-weight: 600; }
.note { display: flex; align-items: flex-start; gap: 12px; padding: 20px 0; margin-top: 18px; color: var(--muted); font-size: 12px; }
.note > svg { margin-top: 2px; width: 17px; height: 17px; }
.note p { max-width: 820px; }
.glossary-callout { display: flex; gap: 22px; padding: 30px; border-radius: 20px; background: var(--surface); border: 1px solid var(--border); margin-top: 30px; }
.glossary-callout h2 { font: 600 26px/1.25 var(--body); letter-spacing: -.025em; }
.glossary-callout p { margin-top: 10px; color: var(--muted); font-size: 14px; }
.term-links { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 20px; }
.term-links a { font-size: 13px; background: var(--background); padding: 6px 13px; border: 1px solid var(--border); border-radius: 20px; text-decoration: none; }
.term-links a:hover { border-color: var(--muted); }
.topic-page { max-width: 820px; padding-top: 36px; }
.topic-header { margin-block: 40px 32px; }
.topic-header h1 { overflow-wrap: anywhere; }
.topic-header p { margin-top: 20px; max-width: 630px; color: var(--muted); font-size: 18px; }
.tradeoff-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-block: 32px 40px; }
.tradeoff-panel { padding: 24px; border: 1px solid var(--border); border-radius: 18px; }
.tradeoff-panel h2 { display: flex; align-items: center; gap: 10px; font-size: 16px; font-weight: 600; }
.tradeoff-panel ul { margin: 16px 0 0; padding-left: 18px; font-size: 14px; color: var(--muted); }
.tradeoff-panel li + li { margin-top: 10px; }
.reading { max-width: 690px; font-size: 16px; }
.reading h2 { font: 600 24px/1.3 var(--body); letter-spacing: -.025em; margin-block: 36px 14px; scroll-margin-top: 28px; }
.reading h3 { font-size: 18px; margin-block: 24px 12px; }
.reading p { margin-block: 12px; }
.reading li { margin-block: 8px; }
.reading a { text-decoration-color: var(--muted); }
.reading a:hover { text-decoration-color: var(--ink); }
.reading strong { font-weight: 600; }
.related-topics { border-top: 1px solid var(--border); margin-top: 24px; padding-top: 24px; }
.related-topics h2 { font-size: 16px; font-weight: 600; }
.glossary-index { display: flex; flex-wrap: wrap; gap: 8px; border-block: 1px solid var(--border); padding-block: 22px; margin-bottom: 40px; }
.glossary-index a { font-size: 13px; border-radius: 20px; background: var(--soft); padding: 5px 12px; text-decoration: none; }
.glossary-index a:hover { box-shadow: inset 0 0 0 1px var(--muted); }
.glossary h2 { padding-top: 22px; border-top: 1px solid var(--border); }
.glossary h2:target { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 6px; }

@media (max-width: 1100px) {
.investment-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.card-summary { min-height: 3.2em; }
}
@media (max-width: 760px) {
.intro { padding-block: 48px; }
.intro-copy { font-size: 16px; }
.text-link { margin-left: 0; display: block; }
.basics-grid { grid-template-columns: 1fr; gap: 8px; }
.basic-card { gap: 4px; padding: 16px 18px; }
.section-nav a:last-child { margin-left: 0; }
.investment-card { padding: 20px; }
.card-heading { margin-bottom: 20px; }
.glossary-callout { padding: 24px; gap: 14px; }
.glossary-callout > .category-icon { display: none; }
.topic-header { margin-top: 28px; }
.topic-header p { font-size: 16px; }
.tradeoff-panel { padding: 20px; }
}
@media (max-width: 480px) {
.finance-site .brand > span:last-child { max-width: 90px; line-height: 1.25; }
.investment-grid, .tradeoff-grid { grid-template-columns: 1fr; }
.card-summary { min-height: 0; }
.investment-card { padding: 24px; }
.card-heading { margin-bottom: 16px; }
.card-tradeoffs { margin-block: 16px 20px; }
.section-nav { gap: 4px; }
.section-nav a { font-size: 12px; padding: 8px 12px; }
}
Loading
Loading