diff --git a/README.md b/README.md index c64486f..7c0dec4 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/assets/css/base.css b/assets/css/base.css new file mode 100644 index 0000000..90d297d --- /dev/null +++ b/assets/css/base.css @@ -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; } +} diff --git a/assets/css/finance.css b/assets/css/finance.css new file mode 100644 index 0000000..b476aea --- /dev/null +++ b/assets/css/finance.css @@ -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; } +} diff --git a/assets/css/main.css b/assets/css/main.css index 5744613..0ac0631 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -1,1080 +1,155 @@ -/* --------------------------------------------------------------------------- - riesinger.dev — "logbook" - One typeface (iA Writer Quattro, a writing-tool face) carries everything. - A margin rail holds dates, labels and tags; prose keeps its own column. ---------------------------------------------------------------------------- */ - -@font-face { - font-family: "iA Writer Quattro"; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(/fonts/iAWriterQuattroS-Regular.woff2) format("woff2"); -} - -@font-face { - font-family: "iA Writer Quattro"; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(/fonts/iAWriterQuattroS-Italic.woff2) format("woff2"); -} - -@font-face { - font-family: "iA Writer Quattro"; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(/fonts/iAWriterQuattroS-Bold.woff2) format("woff2"); -} - -@font-face { - font-family: "iA Writer Quattro"; - font-style: italic; - font-weight: 700; - font-display: swap; - src: url(/fonts/iAWriterQuattroS-BoldItalic.woff2) format("woff2"); -} - -:root { - color-scheme: light dark; - - --font-body: - "iA Writer Quattro", ui-sans-serif, system-ui, -apple-system, - "Segoe UI", sans-serif; - --font-mono: - ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; - - --paper: #f0f1f4; - --panel: #f8f9fb; - --ink: #15171c; - --ink-2: #383c45; - --muted: #61666f; - --rule: #d9dbe2; - --rule-strong: #bfc3cc; - --accent: #2645d8; - --accent-soft: rgba(38, 69, 216, 0.3); - --accent-wash: rgba(38, 69, 216, 0.08); - - --gutter: 7.5rem; - --gap: 2.5rem; - --read: 44rem; - --pad: 1.5rem; - - /* The content frame widens on reference pages; the chrome frame never does, - so the header and footer are identical on every page. */ - --frame: 54rem; - --frame-chrome: 54rem; -} - -/* Reference pages (wide tables, data dumps) get a wider content frame. Running - text stays at the reading measure so only the tables use the extra room. */ -body.wide { - --frame: 70rem; -} - -/* These pages carry no margin metadata, so the rail collapses; left in place its - empty gutter would push the content off-centre inside the wider frame. */ -body.wide > main::before { - display: none; -} - -body.wide .rail { - grid-template-columns: minmax(0, 1fr); - column-gap: 0; -} - -body.wide .rail > *, -body.wide .rail > .rail-aside { - grid-column: 1; -} - -body.wide .prose > p, -body.wide .prose > ul, -body.wide .prose > ol, -body.wide .prose > blockquote, -body.wide .prose > h2, -body.wide .prose > h3, -body.wide .doc-subtitle { - max-width: var(--read); -} - -@media (prefers-color-scheme: dark) { - :root { - --paper: #111318; - --panel: #191c22; - --ink: #e9ebf0; - --ink-2: #b5bac4; - --muted: #8a9099; - --rule: #262932; - --rule-strong: #3a3e49; - --accent: #93a5ff; - --accent-soft: rgba(147, 165, 255, 0.36); - --accent-wash: rgba(147, 165, 255, 0.1); - } -} - -/* --------------------------------------------------------------- base ---- */ - -*, -*::before, -*::after { - box-sizing: border-box; -} - -html { - font-family: var(--font-body); - font-variant-numeric: tabular-nums; - -webkit-text-size-adjust: 100%; -} - -body { - margin: 0; - padding: 0; - background: var(--paper); - color: var(--ink-2); - font-size: 1.09375rem; - line-height: 1.7; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -a { - color: inherit; - text-decoration: none; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - color: var(--ink); - font-weight: 700; - letter-spacing: -0.02em; - line-height: 1.15; - text-wrap: balance; -} - -::selection { - background: var(--accent); - color: var(--paper); -} - -:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 3px; - border-radius: 2px; -} - -img, -video, -figure { - max-width: 100%; -} - -.skip-link { - position: absolute; - left: -9999px; - top: 0; - z-index: 10; - padding: 0.6rem 1rem; - background: var(--accent); - color: var(--paper); - font-size: 0.8125rem; -} - -.skip-link:focus { - left: 0.5rem; - top: 0.5rem; -} - -/* ------------------------------------------------------------- shell ---- */ - -body > header, -body > footer, -body > main { - width: 100%; - max-width: calc(var(--frame) + var(--pad) * 2); - margin-inline: auto; - padding-inline: var(--pad); -} - -/* Centred on the chrome frame rather than the content frame, so a wide page's - header sits in exactly the same place as every other page's. */ -body > header, -body > footer { - max-width: calc(var(--frame-chrome) + var(--pad) * 2); -} - -body > main { - position: relative; - padding-bottom: 4rem; -} - -/* The margin rail: a ruled notebook line separating metadata from prose. */ -body > main::before { - content: ""; - position: absolute; - top: 0; - bottom: 3rem; - left: calc(var(--pad) + var(--gutter) + var(--gap) / 2); - width: 1px; - background: var(--rule); -} - -.site-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 1.5rem; - padding-block: 1.75rem 3.5rem; -} - -.wordmark { - font-size: 1rem; - font-weight: 700; - letter-spacing: -0.01em; - color: var(--ink); -} - -.wordmark span { - color: var(--accent); - font-weight: 400; -} - -.wordmark:hover { - color: var(--accent); -} - -.site-nav ul { - display: flex; - gap: 1.5rem; - margin: 0; - padding: 0; - list-style: none; -} - -.site-nav a { - font-size: 0.75rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.13em; - color: var(--muted); -} - -.site-nav a:hover { - color: var(--ink); -} - -.site-nav a[aria-current] { - color: var(--ink); - box-shadow: inset 0 -1px 0 0 var(--accent); -} - -.site-footer { - display: flex; - flex-wrap: wrap; - align-items: baseline; - justify-content: space-between; - gap: 0.75rem 1.5rem; - padding-block: 1.5rem 3rem; - border-top: 1px solid var(--rule); - font-size: 0.8125rem; - color: var(--muted); -} - -.site-footer a:hover { - color: var(--accent); -} - -/* -------------------------------------------------------- gutter grid ---- */ - -.rail { - display: grid; - grid-template-columns: var(--gutter) minmax(0, 1fr); - column-gap: var(--gap); - align-items: start; -} - -.rail > * { - grid-column: 2; -} - -.rail > .rail-aside { - grid-column: 1; -} - -.rail-gap { - margin-top: 2.25rem; -} - -.label { - font-size: 0.6875rem; - font-weight: 700; - line-height: 1.5; - text-transform: uppercase; - letter-spacing: 0.14em; - color: var(--muted); -} - -/* ------------------------------------------------------------- hero ---- */ - -.hero { - padding-bottom: 1rem; -} - -.hero-name { - margin: 0; - font-size: clamp(2.75rem, 11vw, 5.25rem); - line-height: 0.94; - letter-spacing: -0.045em; -} - -.hero-name .surname { - display: block; - color: var(--ink-2); -} - -.hero-lead { - max-width: 30rem; - margin: 1.75rem 0 0; - font-size: 1.125rem; - line-height: 1.6; - color: var(--ink-2); - text-wrap: pretty; -} - -.hero-lead p { - margin: 0; -} - -.hero-lead p + p { - margin-top: 0.9rem; -} - -.hero-lead a { - color: var(--ink); - text-decoration: underline; - text-decoration-color: var(--accent-soft); - text-decoration-thickness: 1px; - text-underline-offset: 0.2em; -} - -.hero-lead a:hover { - color: var(--accent); - text-decoration-color: var(--accent); -} - -/* ------------------------------------------------------- cadence plot ---- */ - -.cadence { - margin-top: 3.25rem; -} - -/* One mark per entry, stacked by year — a tally, not a dashboard. */ -.cadence-plot { - display: flex; - align-items: flex-end; - gap: 0.5rem; - min-height: 2.5rem; - padding-bottom: 0.4rem; - border-bottom: 1px solid var(--rule-strong); -} - -.cadence-year { - display: flex; - flex: 1; - flex-direction: column-reverse; - align-items: center; - gap: 4px; - min-width: 0; - animation: reveal 0.5s cubic-bezier(0.2, 0.7, 0.3, 1) backwards; -} - -.tally { - display: block; - width: 100%; - max-width: 1.75rem; - height: 6px; - border-radius: 1px; - background: var(--accent); -} - -.cadence-year[data-count="0"]::after { - content: ""; - display: block; - width: 100%; - max-width: 1.75rem; - height: 1px; - background: var(--rule-strong); -} - -.cadence-scale { - display: flex; - gap: 0.5rem; - margin-top: 0.5rem; -} - -.cadence-scale span { - flex: 1; - min-width: 0; - font-size: 0.625rem; - font-weight: 700; - letter-spacing: 0.04em; - color: var(--muted); - text-align: center; -} - -.cadence-total { - margin-top: 0.75rem; - font-size: 0.8125rem; - color: var(--muted); -} - -/* ------------------------------------------------------------ blocks ---- */ - -.block { - padding-block: 2.75rem; - border-top: 1px solid var(--rule); -} - -.rail.block-head { - align-items: baseline; - margin-bottom: 0.6rem; -} - -.block-head h2 { - margin: 0; -} - -.block-head .more { - justify-self: end; -} - -.more { - font-size: 0.75rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.12em; - color: var(--muted); - white-space: nowrap; -} - -.more:hover { - color: var(--accent); -} - -/* ------------------------------------------------------------ entries ---- */ - -.entries, -.projects { - margin: 1.5rem 0 0; - padding: 0; - border-top: 1px solid var(--rule); - list-style: none; -} - -.block .entries, -.block .projects { - margin-top: 0; -} - -.entry { - border-bottom: 1px solid var(--rule); -} - -.entry:last-child, -.project:last-child { - border-bottom: none; -} - -.entry-link { - display: grid; - grid-template-columns: var(--gutter) minmax(0, 1fr) auto; - column-gap: var(--gap); - align-items: baseline; - padding: 0.9rem 0.75rem; - margin-inline: -0.75rem; - transition: background-color 0.15s ease; -} - -.entry-link:hover { - background: var(--accent-wash); -} - -.entry-date { - font-size: 0.8125rem; - color: var(--muted); - font-variant-numeric: tabular-nums; -} - -.entry-title { - font-size: 1.0625rem; - font-weight: 700; - letter-spacing: -0.015em; - line-height: 1.35; - color: var(--ink); -} - -.entry-tags { - display: flex; - flex-wrap: wrap; - justify-content: flex-end; - gap: 0.5rem; - font-size: 0.75rem; - color: var(--muted); -} - -.entry-link:hover .entry-title { - color: var(--accent); -} - -.entry-link:hover .entry-date { - color: var(--ink-2); -} - -/* ----------------------------------------------------------- projects ---- */ - -.project { - border-bottom: 1px solid var(--rule); -} - -.project-link { - display: grid; - grid-template-columns: var(--gutter) minmax(0, 1fr); - column-gap: var(--gap); - align-items: start; - padding: 1.25rem 0.75rem; - margin-inline: -0.75rem; - transition: background-color 0.15s ease; -} - -.project-link:hover { - background: var(--accent-wash); -} - -.project-body { - grid-column: 2; -} - -.project-year { - grid-column: 1; - padding-top: 0.2rem; - font-size: 0.8125rem; - color: var(--muted); -} - -.project-title { - margin: 0; - font-size: 1.0625rem; - letter-spacing: -0.015em; -} - -.project-link:hover .project-title { - color: var(--accent); -} - -.project-summary { - margin: 0.25rem 0 0; - font-size: 0.9375rem; - line-height: 1.5; - color: var(--muted); -} - -.project-status { - margin: 0.5rem 0 0; -} - -.doc-meta .project-status { - margin: 0; -} - -.project-status::before { - content: ""; - display: inline-block; - width: 5px; - height: 5px; - margin-right: 0.5em; - border-radius: 50%; - background: var(--rule-strong); - vertical-align: 0.15em; -} - -.project-status[data-status="active"]::before { - background: var(--accent); -} - -/* -------------------------------------------------------------- prose ---- */ - -.prose { - color: var(--ink-2); - overflow-wrap: break-word; -} - -.prose > :first-child { - margin-top: 0; -} - -.about .prose > p:first-child { - color: var(--ink); -} - -.prose p, -.prose ul, -.prose ol, -.prose dl { - margin-block: 1.35em; -} - -.prose li + li { - margin-top: 0.4em; -} - -.prose h2 { - margin: 2.75rem 0 0.85rem; - font-size: 1.5rem; -} - -.prose h3 { - margin: 2.25rem 0 0.7rem; - font-size: 1.1875rem; -} - -.prose h4 { - margin: 1.85rem 0 0.5rem; - font-size: 1.0625rem; -} - -.prose h5, -.prose h6 { - margin: 1.75rem 0 0.5rem; - font-size: 0.6875rem; - text-transform: uppercase; - letter-spacing: 0.14em; - color: var(--muted); -} - -.prose a { - color: var(--ink); - text-decoration: underline; - text-decoration-color: var(--accent-soft); - text-decoration-thickness: 1px; - text-underline-offset: 0.2em; -} - -.prose a:hover { - color: var(--accent); - text-decoration-color: var(--accent); -} - -.prose strong { - color: var(--ink); -} - -.prose blockquote { - margin: 1.75rem 0; - padding-left: 1.25rem; - border-left: 2px solid var(--accent); - color: var(--muted); -} - -.prose blockquote p { - margin-block: 0.5em; -} - -.prose hr { - height: 1px; - margin: 2.75rem 0; - border: none; - background: var(--rule); -} - -.prose figure { - margin: 2rem 0; -} - -.prose img { - display: block; - border-radius: 3px; -} - -.prose figcaption { - margin-top: 0.6rem; - font-size: 0.8125rem; - line-height: 1.5; - color: var(--muted); -} - -.scroll-x { - overflow-x: auto; - overscroll-behavior-x: contain; -} - -.prose table { - width: 100%; - margin: 2rem 0; - border-collapse: collapse; - font-size: 0.9375rem; -} - -.prose th { - padding: 0.4rem 0.75rem; - border-bottom: 1px solid var(--rule-strong); - font-size: 0.6875rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.12em; - color: var(--muted); - text-align: left; -} - -.prose td { - padding: 0.45rem 0.75rem; - border-bottom: 1px solid var(--rule); - vertical-align: top; -} - -/* Markdown tables are ruled only along the bottom of each row, so the first - column can sit flush and line its text up with the surrounding prose. Tables - that draw their own cell borders opt back in to a left pad. */ -.prose tr > :first-child { - padding-left: 0; -} - -.prose sup a { - text-decoration: none; - color: var(--accent); -} - -.footnotes { - margin-top: 3rem; - padding-top: 1.25rem; - border-top: 1px solid var(--rule); - font-size: 0.9375rem; - color: var(--muted); -} - -/* --------------------------------------------------------------- code ---- */ - -code { - font-family: var(--font-mono); - font-size: 0.85em; -} - -:not(pre) > code { - padding: 0.1em 0.35em; - border: 1px solid var(--rule); - border-radius: 3px; - background: var(--panel); - color: var(--ink); -} - -.highlight { - margin: 1.75rem 0; -} - -pre { - margin: 1.75rem 0; - padding: 1.1rem 1.25rem; - overflow-x: auto; - border: 1px solid var(--rule); - border-radius: 4px; - background: var(--panel); - font-size: 0.8125rem; - line-height: 1.65; -} - -.highlight pre { - margin: 0; -} - -.chroma { - background: var(--panel) !important; -} - -/* -------------------------------------------------------- document page --- */ - -.doc-title { - margin: 0; - font-size: clamp(1.9rem, 6vw, 2.6rem); - letter-spacing: -0.035em; - line-height: 1.08; -} - -.doc-subtitle { - max-width: 32rem; - margin: 1rem 0 0; - font-size: 1.0625rem; - line-height: 1.55; - color: var(--muted); - text-wrap: pretty; -} - -.doc-meta { - display: flex; - flex-direction: column; - gap: 0.35rem; - padding-top: 0.6rem; - font-size: 0.8125rem; - line-height: 1.5; - color: var(--muted); -} - -.doc-meta .doc-meta-tags { - display: flex; - flex-direction: column; - gap: 0.2rem; - margin: 0; - padding: 0; - list-style: none; -} - -.doc-meta a:hover { - color: var(--accent); -} - -.doc-body { - margin-top: 2.75rem; -} - -.doc-hero { - margin: 2rem 0 0; -} - -.doc-hero img { - width: 100%; - border-radius: 3px; -} - -/* -------------------------------------------------------------- filter --- */ - -.filter-bar { - display: none; - margin-bottom: 1.5rem; -} - -.filter-bar.is-ready { - display: grid; -} - -.filter { - display: flex; - flex-wrap: wrap; - gap: 0.4rem; - margin: 0 0 1.75rem; - padding: 0; - list-style: none; -} - -.filter button { - padding: 0.28rem 0.7rem; - border: 1px solid var(--rule-strong); - border-radius: 999px; - background: transparent; - font: inherit; - font-size: 0.75rem; - line-height: 1.4; - color: var(--muted); - cursor: pointer; - transition: - color 0.15s ease, - border-color 0.15s ease, - background-color 0.15s ease; -} - -.filter button:hover { - color: var(--ink); - border-color: var(--ink-2); -} - -.filter .count { - opacity: 0.65; -} - -.filter-note { - margin: 0.7rem 0 0; - font-size: 0.8125rem; - color: var(--muted); -} - -.filter-note a { - text-decoration: underline; - text-decoration-color: var(--accent-soft); - text-underline-offset: 0.2em; -} - -.filter-note a:hover { - color: var(--accent); -} - -.filter button[aria-pressed="true"] { - background: var(--accent); - border-color: var(--accent); - color: var(--paper); -} - -.entry[hidden] { - display: none; -} - -.filter-empty { - margin: 2rem 0; - color: var(--muted); -} - -/* ------------------------------------------------------------ tag cloud --- */ - -.tag-cloud { - display: flex; - flex-wrap: wrap; - gap: 0.5rem; - margin: 0; - padding: 0; - list-style: none; -} - -.tag-cloud a { - display: inline-flex; - align-items: baseline; - gap: 0.45em; - padding: 0.3rem 0.75rem; - border: 1px solid var(--rule-strong); - border-radius: 999px; - font-size: 0.875rem; - color: var(--ink-2); -} - -.tag-cloud a:hover { - border-color: var(--accent); - color: var(--accent); -} - -.tag-cloud .count { - font-size: 0.75rem; - color: var(--muted); -} - -.tag-cloud a:hover .count { - color: var(--accent); -} - -/* ------------------------------------------------------------- motion ---- */ - -.reveal { - animation: reveal 0.55s cubic-bezier(0.2, 0.7, 0.3, 1) backwards; -} - -.reveal-2 { - animation-delay: 0.09s; -} - -.reveal-3 { - animation-delay: 0.18s; -} - -@keyframes reveal { - from { - opacity: 0; - transform: translateY(0.5rem); - } -} - -@media (prefers-reduced-motion: reduce) { - *, - *::before, - *::after { - animation-duration: 0.001ms !important; - animation-delay: 0ms !important; - transition-duration: 0.001ms !important; - } -} - -/* --------------------------------------------------------- narrow view --- */ - -@media (max-width: 46rem) { - :root { - --pad: 1.25rem; - } - - body > main::before { - display: none; - } - - .rail, - .entry-link, - .project-link { - grid-template-columns: minmax(0, 1fr); - column-gap: 0; - } - - .rail > *, - .rail > .rail-aside { - grid-column: 1; - } - - .rail > .rail-aside { - margin-bottom: 0.6rem; - } - - .entry-link { - grid-template-areas: - "meta" - "title"; - row-gap: 0.2rem; - padding-block: 1rem; - } - - .entry-date { - grid-area: meta; - } - - .entry-title { - grid-area: title; - } - - .entry-tags { - justify-content: flex-start; - margin-top: 0.35rem; - } - - .project-link { - grid-template-areas: - "year" - "body"; - row-gap: 0.35rem; - } - - .project-year { - grid-area: year; - grid-column: auto; - padding-top: 0; - } - - .project-body { - grid-area: body; - grid-column: auto; - } - - .project-thumb { - aspect-ratio: 16 / 7; - } - - .doc-meta { - flex-direction: row; - flex-wrap: wrap; - gap: 0.35rem 1.25rem; - padding-top: 0; - margin-bottom: 1.25rem; - } - - .doc-meta .doc-meta-tags { - flex-direction: row; - gap: 0.75rem; - } - - .site-header { - padding-block: 1.25rem 2.5rem; - } +/* Personal site layouts. Typography, theme and chrome are shared in base.css. */ +.site-nav ul, .footer-links { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; } +.footer-links { gap: 20px; } +.label { display: block; color: var(--muted); font-size: 12px; font-weight: 600; } + +/* Home: introduction, card collections, and a quieter personal note. */ +.hero { max-width: 760px; padding-block: 72px 68px; } +.hero h1 { font-size: clamp(48px, 6vw, 76px); } +.hero-lead { max-width: 600px; margin-top: 24px; color: var(--muted); font-size: 18px; line-height: 1.65; } +.hero-lead p + p { margin-top: 16px; } +.hero-lead a { color: var(--ink); } +.hero-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 16px 24px; margin-top: 28px; } +.hero-actions .button { margin: 0; } +.quiet-link, .more { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; color: var(--muted); font-size: 13px; } +.quiet-link svg, .more svg { width: 16px; height: 16px; } +.quiet-link:hover, .more:hover { color: var(--ink); } +.home-section + .home-section { margin-top: 48px; } +.section-heading { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 20px; } +.section-heading h2 { font: 600 26px/1.25 var(--body); letter-spacing: -.025em; } +.section-heading p { margin-top: 6px; color: var(--muted); font-size: 14px; } +.more { flex-shrink: 0; } +.about-panel { display: grid; grid-template-columns: minmax(160px, 1fr) minmax(0, 2.6fr); gap: 40px; margin-top: 56px; padding: 36px; border: 1px solid var(--border); border-radius: 20px; background: var(--surface); } +.about-panel h2 { font: 600 28px/1.25 var(--body); letter-spacing: -.025em; } +.about-panel .prose { font-size: 15px; color: var(--muted); } +.about-panel .prose > :first-child { color: var(--ink); } +.about-panel .prose > :last-child { margin-bottom: 0; } + +/* Archive cards keep dates, tags, and project status visible. */ +.archive-page { padding-top: 64px; } +.page-heading { margin-bottom: 36px; } +.doc-title { overflow-wrap: anywhere; } +.doc-subtitle { max-width: 660px; margin-top: 20px; font-size: 18px; color: var(--muted); text-wrap: pretty; } +.page-heading .prose { max-width: 720px; margin-top: 24px; } +.entries, .projects { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin: 0; padding: 0; list-style: none; } +.projects { grid-template-columns: repeat(3, minmax(0, 1fr)); } +.entry, .project { min-width: 0; } +.entry-link, .project-link { position: relative; display: flex; flex-direction: column; height: 100%; padding: 26px; border: 1px solid var(--border); border-radius: 18px; text-decoration: none; transition: border-color 150ms ease, background-color 150ms ease; } +.entry-link:hover, .project-link:hover { border-color: var(--muted); background: var(--surface); } +.entry-date, .project-year { display: block; padding-right: 28px; color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; } +.entry-title, .project-title { display: block; margin-top: 16px; font: 600 20px/1.35 var(--body); letter-spacing: -.025em; overflow-wrap: anywhere; } +.entry-summary, .project-summary { margin-top: 12px; color: var(--muted); font-size: 14px; line-height: 1.6; } +.entry-tags { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 20px; margin-top: auto; color: var(--muted); font-size: 11px; } +.entry-tags > span, .project-status { display: inline-flex; align-items: center; width: fit-content; padding: 3px 10px; border-radius: 20px; background: var(--soft); color: var(--muted); font-size: 11px; font-weight: 400; line-height: 1.6; } +.entry-arrow { position: absolute; top: 26px; right: 26px; color: var(--muted); } +.entry-arrow svg { width: 17px; height: 17px; } +.project-body { display: flex; flex-direction: column; flex: 1; align-items: flex-start; } +.project-status { gap: 6px; margin-top: 20px; } +.project-status::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; } +.project-status[data-status="active"] { color: var(--ink); } + +/* Progressive enhancement: the full archive remains readable without JS. */ +.filter-bar { display: none; margin-bottom: 28px; } +.filter-bar.is-ready { display: block; } +.filter-bar > .label { margin-bottom: 12px; } +.filter { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; } +.filter button { display: inline-flex; align-items: baseline; gap: 6px; padding: 8px 14px; border: 1px solid transparent; border-radius: 24px; background: var(--soft); color: var(--muted); font: 13px/1.5 var(--body); cursor: pointer; } +.filter button:hover { border-color: var(--border); color: var(--ink); } +.filter button[aria-pressed="true"] { background: var(--ink); color: var(--background); } +.filter .count { font-size: 11px; opacity: .8; } +.filter-empty, .empty-state { padding: 28px; border: 1px solid var(--border); border-radius: 18px; background: var(--surface); color: var(--muted); } +.filter-empty { margin-top: 20px; } +.tag-cloud { display: flex; flex-wrap: wrap; gap: 12px; margin: 20px 0 0; padding: 0; list-style: none; } +.tag-cloud a { display: inline-flex; align-items: center; gap: 16px; border: 1px solid var(--border); border-radius: 24px; padding: 10px 18px; text-decoration: none; font-size: 15px; } +.tag-cloud a:hover { border-color: var(--muted); background: var(--surface); } +.tag-cloud .count { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; } + +/* Long-form pages keep the same shell, with a narrower reading measure. */ +.document-page { max-width: 820px; padding-top: 36px; } +.document-page > .page-heading { margin-top: 36px; } +.document-page > .page-heading:first-child { margin-top: 20px; } +.document-page .doc-title { font-size: clamp(40px, 5vw, 60px); } +.doc-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 18px; margin-bottom: 20px; color: var(--muted); font-size: 12px; } +.doc-meta .project-status { margin-top: 0; } +.doc-meta-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; } +.doc-meta-tags a, .doc-meta-tags > li > span { display: block; padding: 3px 10px; border-radius: 20px; background: var(--soft); color: var(--muted); text-decoration: none; font-size: 11px; } +.doc-meta-tags a:hover { color: var(--ink); } +.doc-body { max-width: 720px; margin-top: 36px; } +.doc-hero { margin: 32px 0; } +.doc-hero img { display: block; width: 100%; height: auto; border-radius: 18px; } +.reference-page { max-width: 1120px; } +.reference-page .doc-body { max-width: none; } +.reference-page .prose > p, .reference-page .prose > ul, .reference-page .prose > ol { max-width: 720px; } + +/* Markdown content: images, code, tables, quotes and footnotes. */ +.prose { overflow-wrap: break-word; line-height: 1.75; } +.prose > :first-child { margin-top: 0; } +.prose p, .prose ul, .prose ol, .prose dl { margin-block: 1.25em; } +.prose li + li { margin-top: .4em; } +.prose h1, .prose h2 { margin: 44px 0 16px; font: 600 26px/1.3 var(--body); letter-spacing: -.025em; } +.prose h3 { margin: 32px 0 12px; font-size: 21px; line-height: 1.3; font-weight: 600; letter-spacing: -.02em; } +.prose h4, .prose h5, .prose h6 { margin: 28px 0 10px; font-size: 17px; font-weight: 600; line-height: 1.4; } +.prose a { text-decoration: underline; text-decoration-color: var(--muted); } +.prose a:hover { text-decoration-color: var(--ink); } +.prose strong { font-weight: 600; } +.prose blockquote { margin: 28px 0; padding: 18px 24px; border: 1px solid var(--border); border-radius: 16px; background: var(--surface); color: var(--muted); } +.prose blockquote p { margin-block: 8px; } +.prose hr { margin: 40px 0; height: 1px; border: 0; background: var(--border); } +.prose figure { margin: 32px 0; } +.prose img { display: block; height: auto; border-radius: 14px; } +.prose figcaption { margin-top: 10px; font-size: 12px; line-height: 1.5; color: var(--muted); } +.prose audio { display: block; width: 100%; margin-block: 24px; } +.prose table { width: 100%; margin: 28px 0; border-collapse: collapse; font-size: 14px; line-height: 1.5; } +.prose > table { display: block; overflow-x: auto; } +.prose th { padding: 12px 16px; background: var(--soft); font-size: 12px; font-weight: 600; text-align: left; } +.prose td { padding: 12px 16px; border-bottom: 1px solid var(--border); vertical-align: top; } +.prose sup a { text-decoration: none; } +.scroll-x { overflow-x: auto; overscroll-behavior-x: contain; } +.footnotes { margin-top: 48px; padding-top: 20px; border-top: 1px solid var(--border); color: var(--muted); font-size: 14px; } +code { font-family: var(--font-mono); font-size: .85em; } +:not(pre) > code { padding: .15em .4em; border: 1px solid var(--border); border-radius: 6px; background: var(--surface); } +.prose > .highlight { margin: 28px 0; } +pre { max-width: 100%; margin: 28px 0; padding: 22px 24px; overflow-x: auto; border: 1px solid var(--border); border-radius: 16px; background: var(--surface); font-size: 13px; line-height: 1.7; } +pre code { font-size: inherit; } +.highlight pre { margin: 0; } +.chroma { background: var(--surface) !important; } + +/* ACRISS retains its decoder and a keyboard-scrollable reference table. */ +.code-input { display: block; width: 100%; max-width: 360px; margin-top: 10px; padding: 12px 16px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); color: var(--ink); font: 14px/1.5 var(--body); } +.code-input::placeholder { color: var(--muted); opacity: 1; } +.code-input:focus-visible { border-color: var(--ink); } +.prose .acriss-table { min-width: 680px; font-family: var(--font-mono); font-size: 13px; } +.prose .acriss-table td { border: 1px solid var(--border); padding: 10px 12px; } +.prose .acriss-table tr:nth-child(even) td { background: var(--surface); } +.prose .acriss-table td.highlight { background: var(--ink); color: var(--background); } + +@media (max-width: 900px) { + .projects { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .about-panel { grid-template-columns: 1fr; gap: 24px; } +} +@media (max-width: 760px) { + .hero { padding-block: 48px; } + .hero-lead { font-size: 17px; } + .archive-page { padding-top: 44px; } + .section-heading { align-items: flex-start; } + .section-heading h2 { font-size: 24px; } + .section-heading p { font-size: 13px; } + .section-heading .more { padding-top: 7px; font-size: 12px; gap: 6px; } + .doc-subtitle { font-size: 16px; } + .entry-link, .project-link { padding: 22px; } + .entry-title, .project-title { font-size: 18px; } + .entry-arrow { top: 22px; right: 22px; } + .about-panel { padding: 28px; } + .prose h1, .prose h2 { font-size: 24px; } + pre { padding: 18px; } +} +@media (max-width: 540px) { + .personal-site .site-header { align-items: flex-start; flex-direction: column; gap: 16px; padding-block: 20px 16px; } + .personal-site .site-nav { width: 100%; } + .site-nav ul { gap: 4px; } + .entries, .projects { grid-template-columns: 1fr; } + .section-heading { flex-wrap: wrap; gap: 10px; } + .section-heading .more { padding-top: 0; } + .about-panel { padding: 24px; } + .document-page .doc-title { font-size: 42px; } } diff --git a/assets/js/page-transitions.js b/assets/js/page-transitions.js new file mode 100644 index 0000000..a3989fe --- /dev/null +++ b/assets/js/page-transitions.js @@ -0,0 +1,58 @@ +// Pair only the selected card title with the next page's h1. Navigation remains +// browser-owned; without this enhancement the CSS-only page fade still works. +(function () { + if (!("onpageswap" in window) || !("onpagereveal" in window) || !window.navigation) return; + + const pendingKey = "riesinger:heading-transition"; + const reducedMotion = matchMedia("(prefers-reduced-motion: reduce)"); + + window.addEventListener("pageswap", function (event) { + if (!event.viewTransition || !event.activation || reducedMotion.matches) return; + + for (const title of document.querySelectorAll("[data-transition-title]")) { + if (title.closest("a").href !== event.activation.entry.url) continue; + + // Hand off just this navigation's identity, never coordinates or HTML. + // Storage may be unavailable; in that case retain the ordinary fade. + try { + sessionStorage.setItem(pendingKey, JSON.stringify({ + from: location.href, + to: event.activation.entry.url, + })); + } catch { + return; + } + + title.style.viewTransitionName = "page-title"; + event.viewTransition.finished.then(function () { + title.style.removeProperty("view-transition-name"); + }); + return; + } + }); + + window.addEventListener("pagereveal", function (event) { + let pending; + try { + const stored = sessionStorage.getItem(pendingKey); + sessionStorage.removeItem(pendingKey); + pending = stored ? JSON.parse(stored) : null; + } catch { + return; + } + + if (!event.viewTransition || reducedMotion.matches || + pending?.to !== location.href || + pending?.from !== window.navigation?.activation?.from?.url) return; + + const title = document.querySelector("main h1"); + if (!title) return; + + title.style.viewTransitionName = "page-title"; + document.documentElement.dataset.headingTransition = ""; + event.viewTransition.finished.then(function () { + title.style.removeProperty("view-transition-name"); + delete document.documentElement.dataset.headingTransition; + }); + }); +})(); diff --git a/content/acriss.md b/content/acriss.md index 166aabd..fee1a88 100644 --- a/content/acriss.md +++ b/content/acriss.md @@ -3,64 +3,14 @@ title: "ACRISS Car Codes" wide: true --- - This is a mirror of the data on https://acriss.org/car-codes/, since it's too slow of a site for my tastes. - + + -
- +
+
diff --git a/content/finance-intro/_index.md b/content/finance-intro/_index.md new file mode 100644 index 0000000..118a395 --- /dev/null +++ b/content/finance-intro/_index.md @@ -0,0 +1,6 @@ +--- +title: Finanzen verstehen +summary: Ein einfacher Einstieg ins Sparen und Investieren – mit kurzen ErklĂ€rungen, Vor- und Nachteilen und einem Glossar. +--- + +Du musst nicht alles auf einmal wissen. Hier lernst du die wichtigsten Geldanlagen kennen – und findest heraus, worin sie sich unterscheiden. diff --git a/content/finance-intro/aktien.md b/content/finance-intro/aktien.md new file mode 100644 index 0000000..c2a1466 --- /dev/null +++ b/content/finance-intro/aktien.md @@ -0,0 +1,32 @@ +--- +title: Aktien +summary: Mit einer Aktie besitzt du einen kleinen Anteil an einem Unternehmen. +weight: 5 +category: market +label: Unternehmen besitzen +benefit: An Unternehmensentwicklung teilhaben +drawback: Einzelne Firmen können scheitern +benefits: + - Kursgewinne und Dividenden sind möglich + - Unternehmen gezielt selbst auswĂ€hlen +drawbacks: + - Hohe Schwankungen bis zum Totalverlust möglich + - Auswahl und breite Streuung erfordern Aufwand +--- + +## So funktioniert’s + +Du kaufst eine [Aktie](/finance-intro/glossar/#aktie) ĂŒber einen [Broker](/finance-intro/glossar/#broker) und verwahrst sie im [Depot](/finance-intro/glossar/#depot). Der Kurs verĂ€ndert sich; manche Unternehmen zahlen außerdem einen Teil ihres Gewinns als Dividende aus, aber nicht garantiert. + +## Wann passt das? + +Wenn du dich mit Unternehmen beschĂ€ftigen möchtest und Verluste finanziell tragen kannst. Geld fĂŒr baldige Ausgaben gehört nicht in eine Anlage, deren Verkaufspreis stark schwanken kann. + +## Gut zu wissen + +Eine bekannte Marke ist noch keine sichere Geldanlage. [Diversifikation](/finance-intro/glossar/#diversifikation) ĂŒber viele Unternehmen, LĂ€nder und Branchen senkt die AbhĂ€ngigkeit von einzelnen Firmen, beseitigt aber nicht das Marktrisiko; Kauf- und Verkaufskosten mindern die [Rendite](/finance-intro/glossar/#rendite). + +## Quellen + +- [BaFin: Aktien auf einen Blick](https://www.bafin.de/DE/verbraucherinnen-verbraucher/themen-finanzprodukte/geldanlage/wertpapiere/aktien/aktien.html) +- [Verbraucherzentrale: Investmentfonds und Risikostreuung](https://www.verbraucherzentrale.de/wissen/geld-versicherungen/sparen-und-anlegen/investmentfonds-das-wichtigste-im-ueberblick-16618) diff --git a/content/finance-intro/anleihen.md b/content/finance-intro/anleihen.md new file mode 100644 index 0000000..9acbfc0 --- /dev/null +++ b/content/finance-intro/anleihen.md @@ -0,0 +1,32 @@ +--- +title: Anleihen +summary: Mit einer Anleihe leihst du einem Staat oder Unternehmen Geld zu festgelegten Bedingungen. +weight: 8 +category: market +label: Geld verleihen +benefit: Vereinbarte Zahlungen und FĂ€lligkeit +drawback: Schuldnerausfall und Kursverluste möglich +benefits: + - Bei klassischen Anleihen feste Zinszahlungen vereinbart + - Laufzeit gezielt auswĂ€hlbar +drawbacks: + - Herausgeber kann Zinsen oder RĂŒckzahlung schuldig bleiben + - Steigende Marktzinsen können den Kurs drĂŒcken +--- + +## So funktioniert’s + +Der Herausgeber einer Anleihe heißt Emittent und schuldet dir die vereinbarten Zahlungen. Bei einer klassischen festverzinslichen Anleihe sind das laufende Zinsen und am Ende der Nennbetrag, sofern der Schuldner zahlungsfĂ€hig bleibt. + +## Wann passt das? + +Wenn du Zahlungszeitpunkte planen möchtest und die ZahlungsfĂ€higkeit des Schuldners sowie die Bedingungen beurteilen kannst. Eine einzelne Anleihe und ein Anleihenfonds sind nicht dasselbe: Viele Fonds ersetzen fĂ€llige Anleihen laufend und haben keinen festen RĂŒckzahlungstermin. + +## Gut zu wissen + +Auch Staatsanleihen haben Ausfall- und ZinsĂ€nderungsrisiken: Steigen Marktzinsen, fallen meist die Kurse bestehender festverzinslicher Anleihen, besonders bei langer Restlaufzeit. Verkaufst du vor FĂ€lligkeit, sind deshalb Verluste möglich; der Kaufpreis kann außerdem vom spĂ€ter zurĂŒckgezahlten Nennbetrag abweichen. Der Kupon, also der vereinbarte Zins auf den Nennbetrag, ist daher nicht gleich deiner [Rendite](/finance-intro/glossar/#rendite); Anleihen fallen nicht unter die [Einlagensicherung](/finance-intro/glossar/#einlagensicherung). + +## Quellen + +- [Verbraucherzentrale: Bundeswertpapiere und Anleihen-ETFs](https://www.verbraucherzentrale.de/wissen/geld-versicherungen/sparen-und-anlegen/bundeswertpapiere-und-anleihenetfs-alternativen-zum-festgeld-102635) +- [Verbraucherzentrale: Risiken von Rentenfonds und Anleihen](https://www.verbraucherzentrale.de/wissen/geld-versicherungen/sparen-und-anlegen/investmentfonds-das-wichtigste-im-ueberblick-16618) diff --git a/content/finance-intro/bausparvertrag.md b/content/finance-intro/bausparvertrag.md new file mode 100644 index 0000000..07e3ffa --- /dev/null +++ b/content/finance-intro/bausparvertrag.md @@ -0,0 +1,32 @@ +--- +title: Bausparvertrag +summary: Ein Bausparvertrag verbindet eine Sparphase mit der Möglichkeit eines spĂ€teren Wohnkredits. +weight: 4 +category: classic +label: Wohnen planen +benefit: SpĂ€terer Darlehenszins vorab vereinbart +drawback: GebĂŒhren und feste Bedingungen +benefits: + - Darlehenskonditionen frĂŒhzeitig vereinbart + - Förderung bei erfĂŒllten Voraussetzungen möglich +drawbacks: + - AbschlussgebĂŒhr belastet das Sparguthaben + - Auszahlungstermin nicht von Beginn an garantiert +--- + +## So funktioniert’s + +Zuerst sparst du einen Teil der vereinbarten Bausparsumme an. Wenn die Zuteilungsvoraussetzungen erfĂŒllt sind, kannst du zusĂ€tzlich ein Bauspardarlehen beantragen; dafĂŒr mĂŒssen auch KreditwĂŒrdigkeit und gegebenenfalls Sicherheiten passen. + +## Wann passt das? + +Wenn du eine konkrete spĂ€tere Wohnfinanzierung oder Modernisierung planst und die gesamten Kosten vergleichen möchtest. Als bloßer Spartopf ist der Vertrag wegen GebĂŒhren und oft niedriger Guthabenzinsen nicht automatisch sinnvoll. + +## Gut zu wissen + +Das Darlehen ist fĂŒr wohnwirtschaftliche Zwecke vorgesehen und muss zurĂŒckgezahlt werden; ein vorher genannter Zuteilungstermin ist zunĂ€chst nur eine SchĂ€tzung. PrĂŒfe Tarifbedingungen, Spar- und Tilgungsraten sowie AbschlussgebĂŒhr; staatliche Förderung hĂ€ngt unter anderem von Einkommen und Verwendung ab. FĂŒr das Sparguthaben ist die [Einlagensicherung](/finance-intro/glossar/#einlagensicherung) des konkreten Instituts zu prĂŒfen, nicht pauschal der ganze Vertrag als geschĂŒtzt anzusehen. + +## Quellen + +- [Verbraucherzentrale: Lohnt sich ein Bausparvertrag?](https://www.verbraucherzentrale.de/wissen/geld-versicherungen/bau-und-immobilienfinanzierung/lohnt-sich-ein-bausparvertrag-7024) +- [BaFin: Einlagensicherung und AnlegerentschĂ€digung](https://www.bafin.de/DE/verbraucherinnen-verbraucher/themen-finanzprodukte/geldanlage/einlagensicherung-anlegerentschaedigung/einlagensicherung-anlegerentschaedigung_node.html) diff --git a/content/finance-intro/etfs.md b/content/finance-intro/etfs.md new file mode 100644 index 0000000..fcda87e --- /dev/null +++ b/content/finance-intro/etfs.md @@ -0,0 +1,31 @@ +--- +title: ETFs +summary: Ein breit gestreuter Aktien-ETF bĂŒndelt Beteiligungen an vielen Unternehmen in einem Fonds. +weight: 6 +category: market +label: Breit gestreut anlegen +benefit: Viele Unternehmen in einem Fonds +drawback: Auch breite MĂ€rkte können stark fallen +benefits: + - Streuung ĂŒber viele LĂ€nder und Branchen möglich + - Meist geringere laufende Kosten als aktive Fonds +drawbacks: + - Starke und langjĂ€hrige Verlustphasen möglich + - Kein Schutz vor allgemeinen Börsenverlusten +--- + +## So funktioniert’s + +Ein [ETF](/finance-intro/glossar/#etf) ist ein börsengehandelter Fonds; hier geht es um Aktien-ETFs, die einen breiten [Index](/finance-intro/glossar/#index) nachbilden. Du kaufst Anteile ĂŒber ein [Depot](/finance-intro/glossar/#depot), einmalig oder regelmĂ€ĂŸig per [Sparplan](/finance-intro/glossar/#sparplan). + +## Wann passt das? + +Wenn du langfristig an vielen Unternehmen beteiligt sein möchtest, ohne jede Aktie selbst auszuwĂ€hlen. DafĂŒr brauchst du Geld, auf das du lange verzichten kannst, und die Bereitschaft, auch deutliche Kursverluste auszuhalten. + +## Gut zu wissen + +Nicht jeder ETF ist breit gestreut: Branchen-, Themen- oder einzelne LĂ€nder-ETFs können stark konzentriert sein, und es gibt auch ETFs auf andere Anlageklassen. Vergleiche die [Kostenquote (TER)](/finance-intro/glossar/#ter) und zusĂ€tzliche Handelskosten; [Sondervermögen](/finance-intro/glossar/#sondervermoegen) schĂŒtzt nicht vor Kursverlusten. [AusschĂŒttende](/finance-intro/glossar/#ausschuettend) und [thesaurierende](/finance-intro/glossar/#thesaurierend) Varianten unterscheiden sich darin, wie sie ErtrĂ€ge verwenden. + +## Quellen + +- [Verbraucherzentrale: Welche Vorteile und Nachteile haben ETFs?](https://www.verbraucherzentrale.de/wissen/geld-versicherungen/sparen-und-anlegen/welche-vorteile-und-nachteile-haben-etfs-16603) diff --git a/content/finance-intro/festgeld.md b/content/finance-intro/festgeld.md new file mode 100644 index 0000000..c39a785 --- /dev/null +++ b/content/finance-intro/festgeld.md @@ -0,0 +1,32 @@ +--- +title: Festgeld +summary: Bei Festgeld legst du Geld fĂŒr eine vereinbarte Zeit zu einem festen Zinssatz an. +weight: 2 +category: classic +label: Planbar sparen +benefit: Fester Zins fĂŒr die Laufzeit +drawback: Geld ist wĂ€hrenddessen gebunden +benefits: + - Zinsertrag ist vorab berechenbar + - Einlagensicherung bei erfassten Banken +drawbacks: + - Vorzeitige Auszahlung meist nicht möglich + - Steigende Marktzinsen kommen dir nicht zugute +--- + +## So funktioniert’s + +Du legst einen Betrag fĂŒr eine feste Laufzeit an. Die Bank vereinbart den Zinssatz mit dir; wann die Zinsen ausgezahlt werden, steht im Vertrag. + +## Wann passt das? + +Wenn du sicher weißt, dass du einen bestimmten Betrag wĂ€hrend der Laufzeit nicht brauchst. FĂŒr eine sofort verfĂŒgbare Notfallreserve fehlt die nötige [LiquiditĂ€t](/finance-intro/glossar/#liquiditaet). + +## Gut zu wissen + +PrĂŒfe Mindestbetrag, Zinsgutschrift und eine mögliche automatische VerlĂ€ngerung. Die [Einlagensicherung](/finance-intro/glossar/#einlagensicherung) gilt nur fĂŒr erfasste Einlagen und Institute; sie schĂŒtzt nicht vor dem Kaufkraftverlust durch [Inflation](/finance-intro/glossar/#inflation). + +## Quellen + +- [BaFin: Festgeld](https://www.bafin.de/DE/verbraucherinnen-verbraucher/themen-finanzprodukte/geldanlage/spareinlagen/festgeld/festgeld.html) +- [BaFin: Einlagensicherung und AnlegerentschĂ€digung](https://www.bafin.de/DE/verbraucherinnen-verbraucher/themen-finanzprodukte/geldanlage/einlagensicherung-anlegerentschaedigung/einlagensicherung-anlegerentschaedigung_node.html) diff --git a/content/finance-intro/fonds.md b/content/finance-intro/fonds.md new file mode 100644 index 0000000..f317dbe --- /dev/null +++ b/content/finance-intro/fonds.md @@ -0,0 +1,32 @@ +--- +title: Aktiv verwaltete Fonds +summary: Bei einem aktiven Fonds wĂ€hlt ein Management die Anlagen nach einer festgelegten Strategie aus. +weight: 7 +category: market +label: Auswahl abgeben +benefit: Management ĂŒbernimmt die Auswahl +drawback: Höhere Kosten ohne Erfolgsgarantie +benefits: + - Keine eigene Auswahl jedes einzelnen Wertpapiers nötig + - Verschiedene Anlagen in einem Fonds kombinierbar +drawbacks: + - HĂ€ufig höhere laufende Kosten und AusgabeaufschlĂ€ge + - Management kann schlechter als der Vergleichsmarkt abschneiden +--- + +## So funktioniert’s + +Ein [Fonds](/finance-intro/glossar/#fonds) sammelt Geld vieler Menschen und legt es gemeinsam an. Beim aktiven Fonds entscheidet ein Management ĂŒber KĂ€ufe und VerkĂ€ufe, etwa von Aktien, Anleihen oder Immobilien, je nach Strategie. + +## Wann passt das? + +Wenn du die Auswahl abgeben möchtest und die konkrete Strategie sowie ihre Kosten nachvollziehen kannst. Ob Laufzeit und [Risiko](/finance-intro/glossar/#risiko) passen, hĂ€ngt von den enthaltenen Anlagen ab, nicht vom Wort „Fonds“. + +## Gut zu wissen + +Aktive Verwaltung garantiert keine bessere [Rendite](/finance-intro/glossar/#rendite) als ein passender Vergleichsindex. PrĂŒfe das Basisinformationsblatt auf Risiken, laufende Kosten und mögliche ErfolgsgebĂŒhren; bei offenen Immobilienfonds gelten besondere Halte- und RĂŒckgabefristen. [Sondervermögen](/finance-intro/glossar/#sondervermoegen) ist keine Zusage, dass du deinen Einsatz zurĂŒckbekommst. + +## Quellen + +- [Verbraucherzentrale: Investmentfonds – das Wichtigste im Überblick](https://www.verbraucherzentrale.de/wissen/geld-versicherungen/sparen-und-anlegen/investmentfonds-das-wichtigste-im-ueberblick-16618) +- [Verbraucherzentrale: Aktives Management und ETF-Kosten im Vergleich](https://www.verbraucherzentrale.de/wissen/geld-versicherungen/sparen-und-anlegen/welche-vorteile-und-nachteile-haben-etfs-16603) diff --git a/content/finance-intro/glossar.md b/content/finance-intro/glossar.md new file mode 100644 index 0000000..859d0d9 --- /dev/null +++ b/content/finance-intro/glossar.md @@ -0,0 +1,91 @@ +--- +title: Finanzbegriffe einfach erklĂ€rt +summary: Die wichtigsten Wörter rund ums Sparen und Anlegen in kurzen SĂ€tzen. +weight: 99 +category: glossary +--- + +Du musst diese Begriffe nicht auswendig lernen. Mit der Suchfunktion deines Browsers (Strg+F oder ⌘+F) findest du ein Wort schnell wieder. + +## Aktie {#aktie} + +Ein kleiner Eigentumsanteil an einem Unternehmen. Du kannst durch steigende Kurse und Dividenden Geld verdienen, aber auch deinen gesamten Einsatz verlieren. + +## AusschĂŒttend {#ausschuettend} + +Ein ausschĂŒttender Fonds zahlt ErtrĂ€ge regelmĂ€ĂŸig an dich aus. Die Höhe ist nicht garantiert; fĂŒr eine Wiederanlage musst du dich selbst kĂŒmmern oder eine automatische Wiederanlage einrichten. + +## Broker {#broker} + +Ein Anbieter, ĂŒber den du Wertpapiere kaufen und verkaufen kannst. HĂ€ufig gehört ein Depot dazu; GebĂŒhren und Handelsmöglichkeiten unterscheiden sich. + +## Depot {#depot} + +Das Konto fĂŒr deine Wertpapiere, etwa Aktien und Fondsanteile. Geld fĂŒr KĂ€ufe und Verkaufserlöse lĂ€uft normalerweise ĂŒber ein separates Verrechnungskonto. + +## Diversifikation {#diversifikation} + +Du verteilst dein Geld auf verschiedene Anlagen, Unternehmen, Branchen oder LĂ€nder. Das verringert die AbhĂ€ngigkeit von einzelnen Anlagen, verhindert aber nicht alle Verluste. + +## Einlagensicherung {#einlagensicherung} + +Die gesetzliche Einlagensicherung schĂŒtzt bei erfassten Instituten grundsĂ€tzlich insgesamt bis zu 100.000 Euro je Person und Bank, zum Beispiel auf Tagesgeld-, Festgeld- und Sparkonten. PrĂŒfe Bank und Sicherungssystem: Nicht jedes Produkt ist eine geschĂŒtzte Einlage, und Kursverluste von Wertpapieren sind nicht abgesichert. + +## ETF {#etf} + +ETF steht fĂŒr „Exchange Traded Fund“, also börsengehandelter Fonds; viele ETFs bilden einen Index nach. Das sagt allein noch nichts ĂŒber breite Streuung aus: Ein Themen-ETF kann auf wenige Bereiche konzentriert sein. + +## Fonds {#fonds} + +Ein gemeinsamer Anlagetopf, an dem du Anteile kaufst. Je nach Strategie investiert er beispielsweise in Aktien, Anleihen oder Immobilien; ETFs sind ebenfalls Fonds. + +## Freistellungsauftrag {#freistellungsauftrag} + +Damit beauftragst du eine Bank, KapitalertrĂ€ge bis zum zugewiesenen Betrag ohne Abzug von Kapitalertragsteuer auszuzahlen. Alle deine FreistellungsauftrĂ€ge zusammen dĂŒrfen den fĂŒr dich geltenden Sparer-Pauschbetrag nicht ĂŒbersteigen. + +## Index {#index} + +Eine Kennzahl fĂŒr die Entwicklung einer nach festen Regeln ausgewĂ€hlten Gruppe von Anlagen. Ein Aktienindex kann viele LĂ€nder abdecken oder sich nur auf ein Land oder eine Branche beschrĂ€nken. + +## Inflation {#inflation} + +Das allgemeine Preisniveau steigt: FĂŒr denselben Geldbetrag kannst du weniger kaufen. Auch wenn dein Kontostand wĂ€chst, kann seine Kaufkraft sinken, wenn Preise stĂ€rker steigen als dein Ertrag nach Kosten und Steuern. + +## Kostenquote (TER) {#ter} + +Die „Total Expense Ratio“ nennt bestimmte jĂ€hrlich anfallende Fondskosten als Prozentsatz des Fondsvermögens; sie werden aus dem Fonds bezahlt. Trotz des Namens sind nicht alle Kosten enthalten, etwa HandelsgebĂŒhren deines Brokers und Transaktionskosten innerhalb des Fonds. + +## LiquiditĂ€t {#liquiditaet} + +Wie schnell du eine Anlage zu Geld machen und darĂŒber verfĂŒgen kannst. Schnelle VerkĂ€uflichkeit bedeutet nicht, dass du ohne Verlust verkaufen kannst. + +## Rendite {#rendite} + +Der Gewinn oder Verlust einer Anlage im VerhĂ€ltnis zum eingesetzten Geld, meist als Prozentwert pro Jahr angegeben. Achte darauf, ob Kosten, Steuern und Inflation bereits berĂŒcksichtigt sind; ein Guthabenzins allein beschreibt nicht jede Rendite. + +## Risiko {#risiko} + +Die Möglichkeit, dass sich deine Anlage schlechter entwickelt als erwartet und du Geld verlierst. Dazu gehören etwa Kursschwankungen, ZahlungsausfĂ€lle und der Verlust von Kaufkraft. + +## Sondervermögen {#sondervermoegen} + +Bei entsprechend ausgestalteten Investmentfonds wird das Fondsvermögen getrennt vom eigenen Vermögen der Fondsgesellschaft gehalten und gehört bei deren Insolvenz nicht zur Insolvenzmasse. Das schĂŒtzt nicht vor Kursverlusten oder AusfĂ€llen der Anlagen im Fonds. + +## Sparplan {#sparplan} + +Du investierst automatisch regelmĂ€ĂŸig einen festgelegten Betrag, etwa in einen ETF. Das erleichtert die Routine, garantiert aber weder Gewinn noch einen gĂŒnstigen Kaufpreis. + +## Thesaurierend {#thesaurierend} + +Ein thesaurierender Fonds behĂ€lt ErtrĂ€ge im Fonds und legt sie wieder an, statt sie dir auszuzahlen. Das kann den Zinseszinseffekt unterstĂŒtzen, macht die Anlage aber weder risikofrei noch automatisch steuerfrei. + +## Zinseszins {#zinseszins} + +Wenn gutgeschriebene Zinsen mit angelegt werden, können sie selbst wieder Zinsen verdienen. Bei Fonds kann die Wiederanlage von ErtrĂ€gen Ă€hnlich wirken, ihre zukĂŒnftigen ErtrĂ€ge und Kurse sind aber nicht fest zugesagt. + +## Quellen zum Weiterlesen + +- [BaFin: Einlagensicherung und AnlegerentschĂ€digung](https://www.bafin.de/DE/verbraucherinnen-verbraucher/themen-finanzprodukte/geldanlage/einlagensicherung-anlegerentschaedigung/einlagensicherung-anlegerentschaedigung_node.html) +- [Verbraucherzentrale: Investmentfonds – Grundlagen, Kosten und Steuern](https://www.verbraucherzentrale.de/wissen/geld-versicherungen/sparen-und-anlegen/investmentfonds-das-wichtigste-im-ueberblick-16618) +- [Verbraucherzentrale: ETFs, Index und Risikostreuung](https://www.verbraucherzentrale.de/wissen/geld-versicherungen/sparen-und-anlegen/welche-vorteile-und-nachteile-haben-etfs-16603) +- [Finanzverwaltung NRW: Sparer-Pauschbetrag und Freistellungsauftrag](https://www.finanzamt.nrw.de/steuerinfos/privatpersonen/einkuenfte-aus-kapitalvermoegen/sparerpauschbetrag-freistellungsauftrag) diff --git a/content/finance-intro/sparbuch.md b/content/finance-intro/sparbuch.md new file mode 100644 index 0000000..034b725 --- /dev/null +++ b/content/finance-intro/sparbuch.md @@ -0,0 +1,31 @@ +--- +title: Sparbuch +summary: Das klassische Sparbuch ist ein Sparkonto mit meist variablem Zins und Auszahlungsregeln. +weight: 3 +category: classic +label: Klassisch sparen +benefit: Einfaches Sparen ohne Börsenkurse +drawback: GrĂ¶ĂŸere Auszahlungen oft nur mit Frist +benefits: + - RegelmĂ€ĂŸig auch mit kleinen BetrĂ€gen sparen + - Einlagensicherung bei erfassten Banken +drawbacks: + - HĂ€ufig niedrige und verĂ€nderliche Zinsen + - KĂŒndigungsfristen begrenzen die VerfĂŒgbarkeit +--- + +## So funktioniert’s + +Du zahlst Geld auf ein Sparkonto ein; ein Buch oder eine digitale Übersicht dokumentiert dein Guthaben. Es gibt meist keine feste Laufzeit, aber Regeln fĂŒr Auszahlungen. + +## Wann passt das? + +Wenn dir eine einfache, vertraute Sparform wichtig ist und du ihre Bedingungen kennst. Vergleiche Zins und [LiquiditĂ€t](/finance-intro/glossar/#liquiditaet) auch mit Tagesgeld. + +## Gut zu wissen + +HĂ€ufig sind ohne KĂŒndigung nur bis zu 2.000 Euro im Kalendermonat verfĂŒgbar; fĂŒr grĂ¶ĂŸere Summen gilt oft eine dreimonatige KĂŒndigungsfrist. Entscheidend ist dein Vertrag, sonst können Vorschusszinsen anfallen; prĂŒfe außerdem die [Einlagensicherung](/finance-intro/glossar/#einlagensicherung) des Instituts. + +## Quellen + +- [BaFin: Sparkonto und Sparbuch](https://www.bafin.de/DE/verbraucherinnen-verbraucher/themen-finanzprodukte/geldanlage/spareinlagen/sparkonto/sparkonto.html) diff --git a/content/finance-intro/tagesgeld.md b/content/finance-intro/tagesgeld.md new file mode 100644 index 0000000..59f62d6 --- /dev/null +++ b/content/finance-intro/tagesgeld.md @@ -0,0 +1,32 @@ +--- +title: Tagesgeld +summary: Auf einem Tagesgeldkonto bleibt dein Erspartes flexibel verfĂŒgbar. +weight: 1 +category: classic +label: Flexibel sparen +benefit: Ohne feste Laufzeit verfĂŒgbar +drawback: Der Zinssatz kann sinken +benefits: + - Ein- und Auszahlungen ohne feste Laufzeit + - Einlagensicherung bei erfassten Banken +drawbacks: + - Zinsen sind meist variabel + - Inflation kann die Kaufkraft verringern +--- + +## So funktioniert’s + +Du ĂŒberweist Geld auf ein separates Konto und bekommst dafĂŒr Zinsen. FĂŒr Auszahlungen geht es meist zuerst zurĂŒck auf dein Girokonto; Tagesgeld ersetzt kein Konto zum Bezahlen. + +## Wann passt das? + +Wenn du Geld fĂŒr unerwartete Ausgaben oder ein nahes Sparziel zurĂŒcklegen möchtest. Die hohe [LiquiditĂ€t](/finance-intro/glossar/#liquiditaet) ist dabei wichtiger als eine langfristig festgelegte Verzinsung. + +## Gut zu wissen + +Aktionszinsen können nur kurz gelten oder an Bedingungen geknĂŒpft sein. PrĂŒfe die tatsĂ€chliche Bank hinter dem Angebot und ihre [Einlagensicherung](/finance-intro/glossar/#einlagensicherung): Bei erfassten Instituten sind grundsĂ€tzlich insgesamt 100.000 Euro je Person und Bank geschĂŒtzt, nicht je Konto. + +## Quellen + +- [BaFin: Tagesgeld](https://www.bafin.de/DE/verbraucherinnen-verbraucher/themen-finanzprodukte/geldanlage/spareinlagen/tagesgeld/tagesgeld_node.html) +- [BaFin: Einlagensicherung und AnlegerentschĂ€digung](https://www.bafin.de/DE/verbraucherinnen-verbraucher/themen-finanzprodukte/geldanlage/einlagensicherung-anlegerentschaedigung/einlagensicherung-anlegerentschaedigung_node.html) diff --git a/content/posts/clearing-dns-cache-macos/index.md b/content/posts/clearing-dns-cache-macos/index.md index a7b85eb..57022d3 100644 --- a/content/posts/clearing-dns-cache-macos/index.md +++ b/content/posts/clearing-dns-cache-macos/index.md @@ -10,13 +10,9 @@ tags: You're debugging some DNS changes in your network and Safari (or `curl` / any other tool) keeps sending requests to an old DNS entry? With these commands, you can clear your system's DNS cache: -| macOS version | command | -| ------------------- | --------------------------------------------------------------- | -| 12 (Monterey) | `sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder` | -| 11 (Big Sur) | `sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder` | -| 10.15 (Catalina) | `sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder` | -| 10.14 (Mojave) | `sudo killall -HUP mDNSResponder` | -| 10.13 (High Sierra) | `sudo killall -HUP mDNSResponder` | -| 10.12 (Sierra) | `sudo killall -HUP mDNSResponder` | +| macOS version | command | +| ---------------------- | --------------------------------------------------------------- | +| >= 10.15 (Catalina) | `sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder` | +| <= 10.14 (Mojave) | `sudo killall -HUP mDNSResponder` | I hope this helps 🙂 diff --git a/layouts/404.html b/layouts/404.html index 0ef9b76..25e65a8 100644 --- a/layouts/404.html +++ b/layouts/404.html @@ -1,10 +1,13 @@ {{- define "main" }} -
-

404

-

Nothing at this address

-

- The page either moved or never existed. -

+
+ {{ partial "icon" "back" }} Home +
+

404

+

Nothing at this address

+

+ The page either moved or never existed. +

+

Start from the writing index or the diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index 4201f34..e577eb8 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -1,7 +1,7 @@ {{ partial "head" . }} - + {{ partial "header" . }} {{- block "main" . }}{{- end }} diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 3aaade8..6be29eb 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -1,9 +1,12 @@ {{ define "main" }} -

-

{{ .Title }}

- {{ with .Params.subtitle }} -

{{ . }}

- {{ end }} +
+ {{ partial "icon" "back" }} Home +
+

{{ .Title }}

+ {{ with .Params.subtitle }} +

{{ . }}

+ {{ end }} +
{{ .Content }}
{{ end }} diff --git a/layouts/finance-intro/baseof.html b/layouts/finance-intro/baseof.html new file mode 100644 index 0000000..f4ce0fe --- /dev/null +++ b/layouts/finance-intro/baseof.html @@ -0,0 +1,22 @@ + + + {{ partial "head" . }} + + + + {{ block "main" . }}{{ end }} + + + diff --git a/layouts/finance-intro/list.html b/layouts/finance-intro/list.html new file mode 100644 index 0000000..87a2324 --- /dev/null +++ b/layouts/finance-intro/list.html @@ -0,0 +1,74 @@ +{{ define "main" }} +
+
+ Einfach anfangen +

Dein Geld. Dein VerstÀndnis.

+
{{ .Content }}
+ Geldanlagen kennenlernen {{ partial "icon" "arrow" }} + Ein Begriff ist neu? Zum Glossar +
+ +
+
+

Drei Fragen fĂŒr jede Geldanlage

+

Mehr Ertrag, weniger Risiko, jederzeit verfĂŒgbar? Nicht alles geht gleichzeitig.

+
+ +
+ +
+ + {{ range slice + (dict "id" "klassisch" "category" "classic" "icon" "shield" "title" "Klassisch sparen" "subtitle" "Zinsen vereinbaren, Geld zurĂŒcklegen." "description" "Meist ohne tĂ€gliche Kursschwankungen. DafĂŒr können Zinsen niedrig sein oder dein Geld lĂ€nger gebunden bleiben.") + (dict "id" "markt" "category" "market" "icon" "chart" "title" "Am Markt investieren" "subtitle" "An Unternehmen und MĂ€rkten teilhaben." "description" "Wertpapiere können ErtrĂ€ge bringen, aber auch an Wert verlieren. Wie groß das Risiko ist, hĂ€ngt von der konkreten Anlage ab.") + }} +
+
+ {{ partial "icon" .icon }} +

{{ .title }}

{{ .subtitle }}

+
+

{{ .description }}

+ +
+ {{ end }} + +
+ +
+ {{ partial "icon" "book" }} +

Kein Fachwort soll dich aufhalten.

Broker, Depot oder Inflation? Kurz nachschlagen, dann weiterlesen.

+ +
+
+
+{{ end }} diff --git a/layouts/finance-intro/single.html b/layouts/finance-intro/single.html new file mode 100644 index 0000000..8984f8d --- /dev/null +++ b/layouts/finance-intro/single.html @@ -0,0 +1,36 @@ +{{ define "main" }} +
+ {{ partial "icon" "back" }} Zur Übersicht +
+ {{ if eq .Params.category "glossary" }}Zum Nachschlagen{{ else if eq .Params.category "classic" }}Klassisch sparen{{ else }}Am Markt investieren{{ end }} +

{{ .Title }}

+

{{ .Params.summary }}

+
+ {{ if eq .Params.category "glossary" }} + + {{ else }} +
+
+

{{ partial "icon" "plus" }} Vorteile

+
    {{ range .Params.benefits }}
  • {{ . }}
  • {{ end }}
+
+
+

{{ partial "icon" "minus" }} Nachteile

+
    {{ range .Params.drawbacks }}
  • {{ . }}
  • {{ end }}
+
+
+ {{ end }} +
{{ .Content }}
+ {{ if ne .Params.category "glossary" }} + + + {{ end }} +
+{{ end }} diff --git a/layouts/index.html b/layouts/index.html index 5d5fce7..138bb97 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -1,40 +1,40 @@ {{ define "main" }} {{ $posts := where site.RegularPages "Section" "posts" }} {{ $projects := (site.GetPage "/projects").Pages }} -
-
-
-

- {{ .Params.firstName | default "Pascal" }}{{ .Params.lastName | default "Riesinger" }} -

-
{{ .Content }}
+
+
+ Software engineer · Germany +

{{ .Params.firstName | default "Pascal" }} {{ .Params.lastName | default "Riesinger" }}

+
{{ .Content }}
+ - {{ partial "cadence" . }}
{{ with $posts }} -
-
-

Writing

- All {{ len . }} posts +
+
+

Recent writing

Notes from things I’ve built and figured out.

+ All {{ len . }} posts {{ partial "icon" "arrow" }}
- {{ partial "entries" (dict "pages" (first 5 .)) }} + {{ partial "entries" (dict "pages" (first 4 .)) }}
{{ end }} {{ with $projects }} -
-
-

Projects

- All {{ len . }} projects +
+
+

Things I’ve built

Side projects, experiments, and useful little tools.

+ All projects {{ partial "icon" "arrow" }}
{{ partial "projects" (dict "pages" (first 3 .)) }}
{{ end }} {{ with site.GetPage "/about" }} -
-

{{ .Title }}

+
+
Beyond the code

{{ .Title }}

{{ .Content }}
{{ end }} diff --git a/layouts/partials/cadence.html b/layouts/partials/cadence.html deleted file mode 100644 index b83ec7f..0000000 --- a/layouts/partials/cadence.html +++ /dev/null @@ -1,44 +0,0 @@ -{{- /* Posts per year, drawn from the archive itself. */ -}} -{{- $posts := where site.RegularPages "Section" "posts" }} -{{- $counts := dict }} -{{- $first := 9999 }} -{{- $last := 0 }} -{{- range $posts }} -{{- $year := .Date.Year }} -{{- $key := printf "%d" $year }} -{{- $counts = merge $counts (dict $key (add 1 (int (or (index $counts $key) 0)))) }} -{{- if lt $year $first }}{{ $first = $year }}{{ end }} -{{- if gt $year $last }}{{ $last = $year }}{{ end }} -{{- end }} - -{{- if gt $last $first }} -{{- $span := seq $first $last }} -{{- $max := 1 }} -{{- range $counts }}{{ if gt . $max }}{{ $max = . }}{{ end }}{{ end }} - -
-

Entries per year

- - -

- {{ len $posts }} posts between {{ $first }} and {{ $last }}, mostly about whatever I was building at the time. -

-
-{{- end }} diff --git a/layouts/partials/entries.html b/layouts/partials/entries.html index 443ce9a..d5c2e70 100644 --- a/layouts/partials/entries.html +++ b/layouts/partials/entries.html @@ -1,18 +1,22 @@ -{{- /* Dated index rows. Expects a dict: "pages" (page collection). */ -}} +{{- /* Dated entry cards. Expects a dict: "pages" (page collection). */ -}}
    {{- range .pages }} {{- $tags := .Params.tags | default slice }} {{- $slugs := slice }} {{- range $tags }}{{ $slugs = $slugs | append (. | urlize) }}{{ end }} -
  1. +
  2. - {{ .Title }} + {{ .Title }} + {{- with .Params.subtitle | default .Params.summary }} + {{ . | plainify }} + {{- end }} {{- with $tags }} {{- end }} +
  3. {{- end }} diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html index 2bc9148..81f987d 100644 --- a/layouts/partials/footer.html +++ b/layouts/partials/footer.html @@ -1,8 +1,7 @@ -
    + diff --git a/layouts/partials/head.html b/layouts/partials/head.html index c3bd8b0..cee317b 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -1,10 +1,12 @@ - - - - + + + + + + {{ $title := site.Title }} {{ if and .Title (not .IsHome) }} @@ -28,6 +30,13 @@ {{- end }} + {{ $base := resources.Get "css/base.css" | minify | fingerprint }} + + + {{ if eq .Section "finance-intro" }} + {{ $css := resources.Get "css/finance.css" | minify | fingerprint }} + + {{ else }} {{/* Each syntax theme is scoped to its scheme: stacking them would leave light-only token colours behind on a dark background. */}} {{ $main := resources.Get "css/main.css" }} @@ -35,6 +44,11 @@ {{ $dark := printf "@media (prefers-color-scheme: dark) {\n%s\n}" (resources.Get "css/chroma-dark.css").Content | resources.FromString "css/chroma-dark-scoped.css" }} {{ $css := slice $main $light $dark | resources.Concat "css/bundle.css" | minify | fingerprint }} + {{ end }} + + {{/* Register pagereveal before the first rendering opportunity. */}} + {{ $transitions := resources.Get "js/page-transitions.js" | js.Build (dict "minify" true) | fingerprint }} +
CATEGORY