diff --git a/README.md b/README.md index 4c6d8bc..247322a 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,27 @@ mind-map notes. Everything is driven by Trilium's built-in **Public Share** feature plus a few frontend/backend scripts – no external dependencies (except `highlight.js`, vendored in `lib/`). -![Coffee palette](assets/palette.png) +## Themes -*Palette from the [megabyte0x/omarchy-coffee-theme](https://github.com/megabyte0x/omarchy-coffee-theme) (Coffee / Coffee Latte) repository, MIT licensed.* +The share ships with **three themes**, each with a dark and a light variant (toggled via the header +switch / `html.theme-light` + `html.theme-dark`). They live in `theme/` and are set on the blog by +pointing the `shareCss` relation at the matching note – see +[`docs/switch-blog-theme.md`](docs/switch-blog-theme.md) for the step-by-step guide. + +| Theme | File | Palette (dark / light) | Source | +|---|---|---|---| +| **Coffee** (active by default) | `theme/blog_share_theme_coffee.css` | espresso `#1d150f` / latte-cream `#f0e2d0`, caramel `#e0a15c` · cream `#E8E3C3` / ink `#2D1A1D`, berry `#8e2d53` | [megabyte0x/omarchy-coffee-theme](https://github.com/megabyte0x/omarchy-coffee-theme) (MIT) | +| **Harbor** | `theme/blog_share_theme_harbor.css` | near-black `#1b1b1b` / cream `#efebdc`, coral `#e75a50` · paper `#dfe4c4` / ink `#1c2d28`, nord-blue `#5e81ac` | [HANCORE-linux/omarchy-harbor-theme](https://github.com/HANCORE-linux/omarchy-harbor-theme) (MIT) | +| **Gruvbox** | `theme/blog_share_theme_gruvbox.css` | bg `#282828` / fg `#ebdbb2`, accents red/green/yellow/blue | [morhetz/gruvbox](https://github.com/morhetz/gruvbox) (MIT) | + +![Coffee palette](assets/palette-coffee.png) +![Harbor palette](assets/palette-harbor.png) +![Gruvbox palette](assets/palette-gruvbox.png) ## Features -- Coffee dark / Coffee Latte light theme for the share, with a theme toggle in the header. +- Coffee dark / Coffee Latte light theme for the share, with a theme toggle in the header + (Gruvbox and Harbor are available as well – see the [Themes](#themes) section). - Blog index, category pages, sub-categories, tags and tag overview. - **Menu sorting**: articles in the left menu are sorted by publication date (newest first) and labelled `Fri 2026-08-28 ` automatically. All date displays @@ -66,7 +80,9 @@ no external dependencies (except `highlight.js`, vendored in `lib/`). |---|---|---| | `blog_generator.js` | backend script that generates index, feed, sitemap, search data, category & tag pages | code, `application/javascript;env=backend` | | `blog_publish_manager.js` | backend script that mirrors notes between `Unpublished` and the blog | code, `application/javascript;env=backend` | -| `theme/blog_share_theme.css` | the Coffee share theme (Coffee / Coffee Latte) | code, `text/css` | +| `theme/blog_share_theme_coffee.css` | Coffee / Coffee Latte share theme (active by default) | code, `text/css` | +| `theme/blog_share_theme_harbor.css` | Harbor / Harbordark share theme | code, `text/css` | +| `theme/blog_share_theme_gruvbox.css` | Gruvbox light/dark share theme | code, `text/css` | | `theme/favicon.svg` | default site favicon | code (SVG) | | `theme/cookie.woff2` | "Cookie" font for the Buy me a coffee button | file, `font/woff2` | | `lib/highlight.js` | vendored highlight.js | code, `application/javascript` | @@ -124,7 +140,9 @@ Under **`.blog`** create one code note per file, using the file name as the note | Note title | File | mime | |---|---|---| -| `blog_share_theme.css` | `theme/blog_share_theme.css` | `text/css` | +| `blog_share_theme_coffee.css` | `theme/blog_share_theme_coffee.css` | `text/css` | +| `blog_share_theme_harbor.css` | `theme/blog_share_theme_harbor.css` | `text/css` | +| `blog_share_theme_gruvbox.css` | `theme/blog_share_theme_gruvbox.css` | `text/css` | | `favicon` | `theme/favicon.svg` | – (SVG) | | `Cookie` | `theme/cookie.woff2` | `font/woff2` (file note) | | `highlight.js` | `lib/highlight.js` | `application/javascript` | @@ -176,7 +194,7 @@ mime `application/javascript;env=backend`) and `blog_publish_manager` (from | `shareOpenGraphURL` | `https://YOUR-INSTANCE.example.com/` | – | | `shareOpenGraphColor` | `#83a598` | – | | `iconClass` | `bx bx-edit-alt` | – | -| `~shareCss` | → `blog_share_theme.css` | yes | +| `~shareCss` | → `blog_share_theme_coffee.css` (the active theme) | yes | | `~shareFavicon` | → `favicon` | yes | | `~shareTemplate` | → `share template` | yes | | `~shareOpenGraphImage` | → `og-banner` | – | @@ -297,7 +315,10 @@ server { ## Customisation -- **Theme**: edit `theme/blog_share_theme.css` (Coffee / Coffee Latte via `html.theme-light/dark`). +- **Theme**: pick one of `theme/blog_share_theme_{coffee,harbor,gruvbox}.css` and point the blog's + `shareCss` relation at it – see [`docs/switch-blog-theme.md`](docs/switch-blog-theme.md). Each theme + ships dark + light via `html.theme-light/dark`. The 3D viewer and Mermaid rendering read the theme's + CSS variables, so they adapt automatically to whichever theme is active. - **Buy me a coffee**: edit `scripts/bmc_button.js` (link, text, copyright) – the font is referenced via `__COOKIE_FONT_ID__`. - **Category logos**: copy the `examples/` icon + `ignis8_menu_icon.js` pattern to give a @@ -309,6 +330,6 @@ This project is licensed under the **GNU General Public License v3.0** – see [ The repository also contains third-party assets that keep their own licenses: `lib/highlight.js` (BSD-3-Clause), `lib/hljs_line_numbers.js` (MIT), -`theme/cookie.woff2` (SIL OFL 1.1), `assets/palette.png` (MIT) and the embedded +`theme/cookie.woff2` (SIL OFL 1.1), the three palette images `assets/palette-*.png` (MIT) and the embedded Trilium logo in `scripts/bmc_button.js` (AGPL-3.0). See [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) for details. \ No newline at end of file diff --git a/THIRD_PARTY_LICENSES.md b/THIRD_PARTY_LICENSES.md index 3826dbc..2dfb65b 100644 --- a/THIRD_PARTY_LICENSES.md +++ b/THIRD_PARTY_LICENSES.md @@ -8,8 +8,12 @@ The following files in this repository are **not** covered by the GPL-3.0 and ke | `lib/highlight.js` | [Highlight.js](https://github.com/highlightjs/highlight.js) v11.9.0 | [BSD-3-Clause](#bsd-3-clause) | | `lib/hljs_line_numbers.js` | [highlightjs-line-numbers](https://github.com/yury-dymov/highlightjs-line-numbers) | [MIT](#mit-license) | | `theme/cookie.woff2` | "Cookie" font, © 2011 [Ania Kruk](https://fonts.google.com/specimen/Cookie) | [SIL Open Font License 1.1](https://openfontlicense.org/) | -| `assets/palette.png` | Coffee / Coffee Latte palette image generated from [megabyte0x/omarchy-coffee-theme](https://github.com/megabyte0x/omarchy-coffee-theme) (repo: MIT) | [MIT](#mit-license) | -| `theme/blog_share_theme.css` | Coffee / Coffee Latte color scheme from [megabyte0x/omarchy-coffee-theme](https://github.com/megabyte0x/omarchy-coffee-theme) (repo: MIT) | [MIT](#mit-license) | +| `assets/palette-coffee.png` | Coffee / Coffee Latte palette image generated from [megabyte0x/omarchy-coffee-theme](https://github.com/megabyte0x/omarchy-coffee-theme) (repo: MIT) | [MIT](#mit-license) | +| `assets/palette-harbor.png` | Harbor / Harbordark palette image generated from [HANCORE-linux/omarchy-harbor-theme](https://github.com/HANCORE-linux/omarchy-harbor-theme) (repo: MIT) | [MIT](#mit-license) | +| `assets/palette-gruvbox.png` | Gruvbox palette image generated from [morhetz/gruvbox](https://github.com/morhetz/gruvbox) (repo: MIT) | [MIT](#mit-license) | +| `theme/blog_share_theme_coffee.css` | Coffee / Coffee Latte color scheme from [megabyte0x/omarchy-coffee-theme](https://github.com/megabyte0x/omarchy-coffee-theme) (repo: MIT) | [MIT](#mit-license) | +| `theme/blog_share_theme_harbor.css` | Harbor / Harbordark color scheme from [HANCORE-linux/omarchy-harbor-theme](https://github.com/HANCORE-linux/omarchy-harbor-theme) (repo: MIT) | [MIT](#mit-license) | +| `theme/blog_share_theme_gruvbox.css` | Gruvbox color scheme from [morhetz/gruvbox](https://github.com/morhetz/gruvbox) (repo: MIT) | [MIT](#mit-license) | | `lib/3d/three.min.js`, `lib/3d/OrbitControls.js`, `lib/3d/STLLoader.js` | [three.js](https://github.com/mrdoob/three.js) r128 | [MIT](#mit-license) | | `lib/3d/occt-import-js.js`, `lib/3d/occt-import-js.wasm` | [occt-import-js](https://github.com/kovacsv/occt-import-js) (OpenCASCADE, WASM) | [LGPL-2.1](#lgpl-21) | | `lib/3d/occt-wasm-bundle.js`, `lib/3d/occt-wasm.wasm` | [occt-wasm](https://github.com/andymai/occt-wasm) (OpenCASCADE **OCCT V8**, WebAssembly, esbuild-bundled `OcctKernel`) | [MIT OR Apache-2.0](#mit-license) | diff --git a/assets/palette-coffee.png b/assets/palette-coffee.png new file mode 100644 index 0000000..d984c66 Binary files /dev/null and b/assets/palette-coffee.png differ diff --git a/assets/palette-gruvbox.png b/assets/palette-gruvbox.png new file mode 100644 index 0000000..3a271b9 Binary files /dev/null and b/assets/palette-gruvbox.png differ diff --git a/assets/palette-harbor.png b/assets/palette-harbor.png new file mode 100644 index 0000000..dec855c Binary files /dev/null and b/assets/palette-harbor.png differ diff --git a/assets/palette.png b/assets/palette.png deleted file mode 100644 index e42e721..0000000 Binary files a/assets/palette.png and /dev/null differ diff --git a/docs/switch-blog-theme.md b/docs/switch-blog-theme.md new file mode 100644 index 0000000..7847be3 --- /dev/null +++ b/docs/switch-blog-theme.md @@ -0,0 +1,65 @@ +# Switching the blog theme + +The blog theme is **not** selected by a file name – it is controlled by the **`~shareCss` relation** +on the blog root note (`Richard's Blog`) inside Trilium. The relation points at a `text/css` note +that holds the theme stylesheet. Everything below uses the notes of this repository's live blog; +note IDs are given for reference. + +## Available themes + +| Theme | Repo file | Live note | Dark / light | +|---|---|---|---| +| Coffee (default) | `theme/blog_share_theme_coffee.css` | `NqZXcFRGi3II` | espresso / latte-cream | +| Harbor | `theme/blog_share_theme_harbor.css` | `Ep54EDTwKxup` | harbordark / paper | +| Gruvbox | `theme/blog_share_theme_gruvbox.css` | `edhL5cByGwqA` | gruvbox dark / light | + +All three themes include a `html.theme-light` + `html.theme-dark` block, theme-aware **3D viewer** +overlays and **Mermaid** rendering. The 3D viewer reads the theme's CSS variables +(`--background-primary` for the canvas, `--background-active` for the model material), so it adapts +automatically to whichever theme is active – no script changes needed. + +## How the active theme is resolved + +1. The blog root note (`Richard's Blog`, `OKjkpgmXZY1L`) carries `~shareCss` → `blog_share_theme_*.css`. +2. The target note is a `code` note with mime `text/css` living under `.blog` (the share system note). +3. The public share renders the page and loads that note's CSS. + +## Switching themes + +Pick the target note and re-point the relation. The theme note already exists in Trilium (see the +table above), so only the relation needs to change. + +### Option A – via the Trilium UI + +1. Find the target theme note under `.blog` (e.g. `blog_share_theme_gruvbox.css`). +2. Open `Richard's Blog` → Attributes → edit the `~shareCss` relation to point at that note. +3. Hard-refresh the blog (Ctrl+F5). Done. + +### Option B – via ETAPI (scriptable) + +```bash +TOKEN="your-etapi-token" +SERVER="https://notes.familie-zink.org" + +# 1. Delete the current shareCss relation on the blog root (OKjkpgmXZY1L) +curl -X DELETE "$SERVER/etapi/attributes/" -H "Authorization: $TOKEN" + +# 2. Point shareCss at the desired theme note (example: Gruvbox edhL5cByGwqA) +curl -X POST "$SERVER/etapi/attributes" \ + -H "Authorization: $TOKEN" -H "Content-Type: application/json" \ + -d '{"noteId":"OKjkpgmXZY1L","type":"relation","name":"shareCss","value":"edhL5cByGwqA","isInheritable":true}' +``` + +The attribute ID of the old `shareCss` relation can be looked up via +`GET $SERVER/etapi/notes/OKjkpgmXZY1L/attributes` (or the Trilium attribute list on the note). + +### Option C – create a fresh theme note from this repo + +If you want to add or customise a theme on a new Trilium instance: + +1. Create a `code` note with mime `text/css` under `.blog`, title e.g. `blog_share_theme_coffee.css`. +2. Copy the contents of the matching `theme/blog_share_theme_*.css` file into it. +3. Point `~shareCss` on the blog root at the new note (Option A or B). + +> **Tip:** After a theme/content change the page may be cached – do a hard reload. If you run +> nginx proxy caching, also clear the cache (see `AGENTS.md` / the nginx guide). \ No newline at end of file diff --git a/scripts/3d_model_viewer.js b/scripts/3d_model_viewer.js index 77fc5d3..a09bff6 100644 --- a/scripts/3d_model_viewer.js +++ b/scripts/3d_model_viewer.js @@ -232,8 +232,9 @@ var initSize = canvasSize(); var renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(initSize.w, initSize.h); - var isLight = document.documentElement.classList.contains("theme-light"); - renderer.setClearColor(isLight ? 0xE8E3C3 : 0x1d150f, 1); + var cs = getComputedStyle(document.documentElement); + function cssVar(n, fb) { var v = (cs.getPropertyValue(n) || "").trim(); return v || fb; } + renderer.setClearColor(cssVar("--background-primary", "#1d150f"), 1); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(45, initSize.w / initSize.h, 0.1, 1000000); @@ -309,7 +310,7 @@ geo.setAttribute("position", new THREE.Float32BufferAttribute(e.data.positions, 3)); if (e.data.indices) geo.setIndex(new THREE.BufferAttribute(e.data.indices, 1)); fixWinding(geo); - var mat = new THREE.MeshStandardMaterial({ color: isLight ? 0x8e2d53 : 0xe0a15c, metalness: 0.2, roughness: 0.6, side: THREE.DoubleSide, flatShading: false }); + var mat = new THREE.MeshStandardMaterial({ color: cssVar("--background-active", "#e0a15c"), metalness: 0.2, roughness: 0.6, side: THREE.DoubleSide, flatShading: false }); chunkGeometry(geo, group, mat); var tris = (e.data.indices && e.data.indices.length) ? e.data.indices.length / 3 : e.data.positions.length / 9; fit(); @@ -331,7 +332,7 @@ } else { var geo = new THREE.STLLoader().parse(data.buffer); geo.computeVertexNormals(); - var mat = new THREE.MeshStandardMaterial({ color: isLight ? 0x8e2d53 : 0xe0a15c, metalness: 0.25, roughness: 0.55, flatShading: true }); + var mat = new THREE.MeshStandardMaterial({ color: cssVar("--background-active", "#e0a15c"), metalness: 0.25, roughness: 0.55, flatShading: true }); group.add(new THREE.Mesh(geo, mat)); fit(); showCanvas(); diff --git a/theme/blog_share_theme.css b/theme/blog_share_theme_coffee.css similarity index 100% rename from theme/blog_share_theme.css rename to theme/blog_share_theme_coffee.css diff --git a/theme/blog_share_theme_gruvbox.css b/theme/blog_share_theme_gruvbox.css new file mode 100644 index 0000000..5b37ac3 --- /dev/null +++ b/theme/blog_share_theme_gruvbox.css @@ -0,0 +1,1886 @@ +/* + * Gruvbox Share Theme for Richard's Blog (Trilium Public Share) + * Palette: bg #282828 / #3c3836 / #504945 / #1d2021 fg #ebdbb2 / #fbf1c7 + * red #fb4934 green #b8bb26 yellow #fabd2f + * blue #83a598 purple #d3869b aqua #8ec07c orange #fe8019 + */ + +html.theme-light { + --background-primary: #fbf1c7; + --background-secondary: #ebdbb2; + --background-highlight: #d5c4a1; + --background-active: #83a598; + --blog-card-bg: #ebdbb2; + --scrollbar-thumb: #d5c4a1; + --scrollbar-hover: #bdae93; + --scrollbar-track: #ebdbb2; + --text-primary: #3c3836; + --text-heading: #282828; + --text-menu: #504945; + --text-link: #076678; + --text-menu-active: #fbf1c7; + color-scheme: light; +} + +html.theme-dark { + --background-primary: #282828; + --background-secondary: #1d2021; + --background-highlight: #504945; + --background-active: #83a598; + --blog-card-bg: #3c3836; + --scrollbar-thumb: #504945; + --scrollbar-hover: #665c54; + --scrollbar-track: #1d2021; + --text-primary: #ebdbb2; + --text-heading: #fbf1c7; + --text-menu: #a89984; + --text-link: #83a598; + --text-menu-active: #1d2021; + color-scheme: dark; +} + +body { + font-family: "Inter", "Montserrat", "Lucida Grande", "Lucida Sans Unicode", arial, sans-serif; +} + +/* ---------- Header: Logo durch Laptop-Emoji ---------- */ +#header-logo img { + display: none; +} + +#header-logo::before { + content: "💻"; + font-size: 1.5em; + line-height: 1; + margin-right: 8px; + display: inline-block; + vertical-align: middle; +} + +/* ---------- Buy Me a Coffee (original, lokal) ---------- */ +@font-face { + font-family: "Cookie"; + src: url(/api/notes/__COOKIE_FONT_ID__/download) format("woff2"); + font-weight: 400; + font-display: swap; +} + +#bmc-links { + margin-top: auto; + padding: 8px 25px 4px; + background: var(--background-secondary); + display: flex; + flex-direction: column; + gap: 2px; +} + +.bmc-link { + display: flex; + align-items: center; + gap: 8px; + padding: 4px 6px 4px 24px; + border-radius: 6px; + color: var(--text-heading); + text-decoration: none; + font-size: 0.9em; + transition: background-color 150ms ease, color 150ms ease; +} + +.bmc-link:hover { + background: var(--background-highlight); + color: var(--text-heading); + text-decoration: none; +} + +.bmc-link .tn-icon { + color: var(--text-link); +} + +/* ---------- Menu: wie Footer-Links gestalten ---------- */ +#menu a { + color: var(--text-heading); + gap: 8px; + font-size: 0.9em; + padding: 4px 6px; + border-color: transparent; + transition: background-color 150ms ease, color 150ms ease; +} + +#menu a:hover { + background: var(--background-highlight); + color: var(--text-heading); + border-color: transparent; + text-decoration: none; +} + +#menu a.active { + background: var(--background-active); + color: var(--background-secondary); + border-color: transparent; +} + +#menu .tn-icon { + color: var(--text-link); +} + +#bmc-wrap { + padding: 8px 14px 14px; + background: var(--background-secondary); + border-top: 1px solid var(--background-highlight); +} + +.bmc-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + width: 100%; + box-sizing: border-box; + padding: 6px 12px 8px; + border-radius: 8px; + background: #fabd2f; + color: #1d2021; + border: 2px solid #1d2021; + font-family: "Cookie", "Brush Script MT", cursive; + font-size: 1.4em; + line-height: 1.1; + text-decoration: none; + transition: background-color 150ms ease, transform 150ms ease; +} + +.bmc-btn:hover { + background: #fe8019; + color: #1d2021; + text-decoration: none; + transform: translateY(-1px); +} + +.bmc-btn .bmc-emoji { + font-size: 1.15em; +} + +.bmc-copyright { + margin-top: 8px; + font-size: 0.75em; + color: var(--text-menu); + display: flex; + align-items: center; + justify-content: center; + gap: 4px; + flex-wrap: wrap; +} + +.bmc-powered { + display: inline-flex; + align-items: center; + gap: 3px; + color: var(--text-menu); + text-decoration: none; + transition: color 150ms ease; +} + +.bmc-powered:hover { + color: var(--text-link); + text-decoration: none; +} + +.powered-logo { + width: 1em; + height: 1em; + display: inline-block; +} + +/* ---------- Reading time ---------- */ +.reading-time { + font-size: 0.8em; + color: var(--text-menu); + margin: -0.9em 0 1.25em; +} + +/* ---------- Blog pagination ---------- */ +.blog-pagination { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin: 1.5em 0 0; + padding-top: 1em; + border-top: 1px solid var(--background-highlight); +} + +.blog-pagination .blog-page-num { + font-size: 0.85em; + color: var(--text-menu); +} + +/* ---------- Share footer navigation (built-in prev/next) ausblenden ---------- */ +#content-footer .navigation { + display: none; +} + +/* ---------- Prev/Next ---------- */ +.blog-prevnext { + display: flex; + justify-content: space-between; + gap: 12px; + margin: 1.5em 0 0; + padding-top: 1em; + border-top: 1px solid var(--background-highlight); +} + +.blog-pn { + display: flex; + flex-direction: column; + gap: 2px; + max-width: 45%; + color: var(--text-heading); + text-decoration: none; + transition: color 150ms ease; +} + +.blog-pn.next { + margin-left: auto; + align-items: flex-end; + text-align: right; +} + +.blog-pn-label { + font-size: 0.72em; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--text-menu); +} + +.blog-pn:hover { + color: var(--text-link); + text-decoration: none; +} + +.blog-pn.empty { + display: none; +} + +/* ---------- Search ---------- */ +.blog-search { + margin: 0.5em 0 1em; +} + +.blog-search-input { + width: 100%; + box-sizing: border-box; + padding: 10px 14px; + border-radius: 8px; + border: 1px solid var(--background-highlight); + background: var(--background-secondary); + color: var(--text-heading); + font-size: 1em; +} + +.blog-search-input:focus { + outline: none; + border-color: var(--text-link); +} + +.blog-search-list { + list-style: none; + padding: 0; + margin: 1em 0 0; +} + +.blog-search-hit { + display: flex; + flex-direction: column; + gap: 2px; + padding: 8px 12px; + border-radius: 8px; + border: 1px solid var(--background-highlight); + background: var(--blog-card-bg); + color: var(--text-heading); + text-decoration: none; + margin-bottom: 8px; + transition: border-color 150ms ease; +} + +.blog-search-hit:hover { + border-color: var(--text-link); + text-decoration: none; +} + +.blog-search-path { + font-size: 0.8em; + color: var(--text-menu); +} + +.blog-search-none { + color: var(--text-menu); +} + +/* ---------- Header-Suche (ersetzt eingebaute) ---------- */ +.search-item { + position: relative; +} + +.blog-search-header-input { + flex: 1; + min-width: 0; + padding: 6px 10px 6px 32px; + border-radius: 6px; + border: 1px solid rgba(131, 165, 152, 0.55); + background: rgba(131, 165, 152, 0.08); + color: var(--text-heading); + font-size: 0.9em; + transition: border-color 150ms ease, box-shadow 150ms ease; +} + +html.theme-light .blog-search-header-input { + border-color: #076678; + background: rgba(7, 102, 120, 0.10); +} + +.blog-search-header-input:focus { + outline: none; + border-color: #83a598; + box-shadow: 0 0 0 2px rgba(131, 165, 152, 0.20); +} + +html.theme-light .blog-search-header-input:focus { + border-color: #076678; + box-shadow: 0 0 0 2px rgba(7, 102, 120, 0.15); +} + +.search-item .search-icon { + color: rgba(131, 165, 152, 0.85); +} + +html.theme-light .search-item .search-icon { + color: #076678; +} + +.tn-image { + width: 18px; + height: 18px; + border-radius: 4px; + flex-shrink: 0; + vertical-align: middle; +} + +.tn-image-svg { + color: var(--text-link); +} + +.title-image { + width: 34px; + height: 34px; + border-radius: 6px; + vertical-align: middle; + margin-right: 10px; +} + +.note-fallback { + margin: 1em 0; + overflow: hidden; +} + +.note-fallback-link { + font-size: 0.9em; +} + +.mermaid-fallback { + margin: 1em 0; +} + +.mermaid-render { + margin: 1em 0; + padding: 14px; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow-x: auto; +} + +.mermaid-render svg { + max-width: 100%; + height: auto; +} + +.mermaid-source { + margin: 12px 0 0; + text-align: center; +} + +.mermaid-source summary { + cursor: pointer; + font-size: 0.85em; + color: var(--text-menu); + user-select: none; + padding: 4px 10px; + border: 1px solid var(--background-highlight); + border-radius: 6px; + display: inline-block; + background: var(--background-secondary); +} + +.mermaid-source summary:hover { + color: var(--text-heading); + border-color: var(--text-link); +} + +.mermaid-source pre { + width: min(100%, 820px); + margin: 8px auto 0; + text-align: left; + position: relative; + overflow: hidden; +} + +#content .mermaid-source .hljs-ln { + width: 100%; +} + +/* ---------- Rendered widgets: mind map + excalidraw ---------- */ +.mindmap-render, +.excalidraw-render { + margin: 1em 0; + padding: 14px; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow-x: auto; +} + +.mindmap-svg { + display: block; + width: 100%; + height: auto; +} + +.excalidraw-svg { + display: block; + max-width: 100%; + height: auto; +} + +.mindmap-render svg text { + user-select: none; +} + +.blog-search-overlay { + display: none; + position: absolute; + top: calc(100% + 4px); + left: 0; + right: 0; + z-index: 50; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow: hidden; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); +} + +.blog-search-overlay.open { + display: block; +} + +.blog-search-overlay-hit { + display: flex; + flex-direction: column; + gap: 1px; + padding: 7px 10px; + color: var(--text-heading); + text-decoration: none; + font-size: 0.85em; + border-bottom: 1px solid var(--background-highlight); +} + +.blog-search-overlay-hit:last-child { + border-bottom: none; +} + +.blog-search-overlay-hit:hover { + background: var(--background-highlight); + text-decoration: none; +} + +.blog-search-overlay-hit .s { + font-size: 0.75em; + color: var(--text-menu); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.blog-search-overlay .blog-search-none { + padding: 8px 10px; + font-size: 0.85em; +} + +#main { + max-width: min(92vw, 1200px); +} + +#site-header { + padding-bottom: 10px; +} + +#title { + font-family: "JetBrains Mono", "Montserrat", monospace; + letter-spacing: -0.02em; +} + +body.is-garden #title { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +body.is-garden #title .note-state { + margin-left: auto; + flex-shrink: 0; +} + +body.is-garden #content h1#title { + background-color: rgba(184, 187, 38, 0.35) !important; + border-bottom-color: rgba(184, 187, 38, 0.60) !important; +} + +html.theme-light body.is-garden #content h1#title { + background-color: rgba(184, 187, 38, 0.20) !important; + border-bottom-color: rgba(184, 187, 38, 0.45) !important; +} + +/* ---------- Blog index (generated article list) ---------- */ +.blog-post { + padding: 1.2em 1.4em; + margin-bottom: 1.25em; + border: 1px solid var(--background-highlight); + border-radius: 10px; + background: var(--blog-card-bg); + transition: border-color 150ms ease, box-shadow 150ms ease; + cursor: pointer; +} + +.blog-post:last-child { + margin-bottom: 0; +} + +.blog-post:hover { + border-color: var(--text-link); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18); +} + +#content .blog-post:first-of-type { + margin-top: 1.5em; +} + +/* ---------- Blog post thumbnails (Bild links, Teaser rechts) ---------- */ +.blog-post-inner { + display: flex; + gap: 16px; + align-items: stretch; +} + +.blog-thumb-link { + flex: 0 0 auto; + width: min(256px, 35%); + text-decoration: none; +} + +.blog-thumb { + display: block; + width: 100%; + height: 100%; + max-height: 256px; + object-fit: cover; + border-radius: 8px; + border: 1px solid var(--background-highlight); +} + +.blog-post-body { + flex: 1; + min-width: 0; +} + +.blog-post-title { + margin: 0 0 0.25em; +} + +.blog-post-title a { + color: var(--text-heading); + text-decoration: none; + transition: color 150ms ease; +} + +.blog-post-title a:hover { + color: var(--text-link); + text-decoration: none; +} + +.blog-post-meta { + display: flex; + gap: 12px; + font-size: 0.85em; + color: var(--text-menu); + margin-bottom: 0.5em; +} + +.blog-post-date { + font-variant-numeric: tabular-nums; + opacity: 0.85; +} + +.blog-post-category { + background: var(--background-highlight); + border-radius: 8px; + padding: 1px 10px; + color: var(--text-heading); + font-weight: 600; +} + +.blog-post-summary { + margin: 0 0 0.5em; + color: var(--text-primary); +} + +.blog-post-tags { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.tag { + font-size: 0.78em; + color: var(--text-link); + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + padding: 1px 8px; +} + +a.tag { + text-decoration: none; + transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease; +} + +a.tag:hover { + background: var(--background-highlight); + border-color: var(--text-link); + color: var(--text-heading); + text-decoration: none; +} + +/* ---------- Article meta (date/category on individual pages) ---------- */ +.article-meta { + display: flex; + gap: 12px; + font-size: 0.9em; + color: var(--text-menu); + margin-bottom: 1em; + padding-bottom: 1em; + border-bottom: 1px solid var(--background-highlight); +} + +/* ---------- Headings (h2-h6) - Gruvbox header boxes ---------- */ +html.theme-dark { + --header-h2-bg: rgba(131, 165, 152, 0.35); + --header-h2-border: rgba(131, 165, 152, 0.7); + --header-h3-bg: rgba(142, 192, 124, 0.25); + --header-h3-border: rgba(142, 192, 124, 0.6); + --header-h4-bg: rgba(250, 189, 47, 0.25); + --header-h4-border: rgba(250, 189, 47, 0.6); + --header-h5-bg: rgba(211, 134, 155, 0.25); + --header-h5-border: rgba(211, 134, 155, 0.6); + --header-h6-bg: rgba(254, 128, 25, 0.25); + --header-h6-border: rgba(254, 128, 25, 0.6); + --header-h1-bg: rgba(251, 73, 52, 0.30); + --header-h1-border: rgba(251, 73, 52, 0.6); +} + +html.theme-light { + --header-h2-bg: rgba(7, 102, 120, 0.18); + --header-h2-border: rgba(7, 102, 120, 0.45); + --header-h3-bg: rgba(121, 116, 14, 0.10); + --header-h3-border: rgba(121, 116, 14, 0.35); + --header-h4-bg: rgba(181, 118, 20, 0.10); + --header-h4-border: rgba(181, 118, 20, 0.35); + --header-h5-bg: rgba(143, 63, 113, 0.10); + --header-h5-border: rgba(143, 63, 113, 0.35); + --header-h6-bg: rgba(175, 58, 3, 0.10); + --header-h6-border: rgba(175, 58, 3, 0.35); + --header-h1-bg: rgba(157, 0, 6, 0.12); + --header-h1-border: rgba(157, 0, 6, 0.40); +} + +#content h1 { + background-color: var(--header-h1-bg); + border-bottom: 2px solid var(--header-h1-border); + border-radius: 4px; + padding: 0.3em 0.4em; + font-size: 1.6em; + font-weight: 700; + margin-top: 1.5em; + margin-bottom: 1.25em; +} + +#content h2 { + background-color: var(--header-h2-bg); + border-bottom: 2px solid var(--header-h2-border); + border-radius: 4px; + padding: 0.25em 0.4em; +} + +#content h3 { + background-color: var(--header-h3-bg); + border-bottom: 2px solid var(--header-h3-border); + border-radius: 4px; + padding: 0.2em 0.35em; +} + +#content h4 { + background-color: var(--header-h4-bg); + border-bottom: 2px solid var(--header-h4-border); + border-radius: 4px; + padding: 0.2em 0.35em; +} + +#content h5 { + background-color: var(--header-h5-bg); + border-bottom: 2px solid var(--header-h5-border); + border-radius: 4px; + padding: 0.2em 0.35em; +} + +#content h6 { + background-color: var(--header-h6-bg); + border-bottom: 2px solid var(--header-h6-border); + border-radius: 4px; + padding: 0.2em 0.35em; +} + +#childLinks { + display: none; +} + +#index { + display: none; +} + +/* ---------- Code blocks - Gruvbox Dark (always, also in light mode) ---------- */ +.ck-content pre, +#content pre { + background-color: #282828; + color: #ebdbb2; + border: 1px solid #504945; + border-radius: 8px; +} + +.ck-content code, +#content code { + background-color: #3c3836; + color: #ebdbb2; + border-color: #504945; + border-radius: 8px; + padding: 0.1em 0.35em; +} + +html.theme-light .ck-content pre, +html.theme-light #content pre { + background-color: #fbf1c7; + color: #3c3836; + border-color: #d5c4a1; +} + +html.theme-light .ck-content code, +html.theme-light #content code { + background-color: #d5c4a1; + color: #3c3836; + border-color: #bdae93; +} + +/* ---------- Eingebettete Bilder: Radius wie Code-Blöcke (8px) ---------- */ +#content figure.image { + margin: 1.25em auto; +} + +#content figure img, +#content img:not(.blog-thumb) { + border-radius: 8px; +} + +/* ---------- 3D model viewer (STL / STEP) ---------- */ +.model-viewer { + position: relative; + box-sizing: border-box; + width: calc(100vw - 24px); + margin: 1em 0; + margin-left: calc(50% - (100vw - 24px) / 2); + background: #1d2021; + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow: hidden; +} + +.model-viewer.model-viewer-inline { + width: 100%; + margin-left: 0; +} + +.model-viewer-data { + position: absolute; + top: 8px; + right: 10px; + z-index: 3; + display: none; + font-size: 0.75em; + color: #a89984; + background: rgba(40, 40, 40, 0.8); + border: 1px solid #504945; + border-radius: 6px; + padding: 2px 10px; + font-variant-numeric: tabular-nums; + pointer-events: none; +} + +.model-viewer-canvas { + position: relative; + width: 100%; + height: min(70vh, 900px); + min-height: 420px; +} + +.model-viewer-status { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + padding: 48px; + box-sizing: border-box; + color: #a89984; + font-size: 0.9em; +} + +.model-viewer-status.error { + color: #fb4934; +} + +.model-viewer-progress { + position: absolute; + left: 0; + right: 0; + bottom: 40px; + height: 6px; + width: min(60%, 480px); + margin: 0 auto; + background: #3c3836; + border-radius: 3px; + overflow: hidden; +} + +.model-viewer-progress-fill { + height: 100%; + width: 0; + background: #b8bb26; + border-radius: 3px; + transition: width 150ms ease; +} + +.model-viewer-progress-fill.indeterminate { + width: 40%; + animation: model-progress 1.1s ease-in-out infinite; +} + +@keyframes model-progress { + 0% { transform: translateX(-100%); } + 100% { transform: translateX(250%); } +} + +.model-viewer-hint { + position: absolute; + top: 8px; + left: 10px; + font-size: 0.75em; + color: #a89984; + z-index: 2; + pointer-events: none; +} + +.model-viewer-caption { + font-size: 0.85em; + font-style: italic; + color: var(--text-menu); + text-align: center; + padding: 4px 12px; + background: var(--background-secondary); + border-top: 1px solid var(--background-highlight); +} + +.model-viewer canvas { + display: block; + width: 100%; + height: 100%; +} + +/* ---------- 3D-Viewer: theme-bewusste Overlays ---------- */ +html.theme-light .model-viewer { + background: #fbf1c7; +} +html.theme-light .model-viewer-status, +html.theme-light .model-viewer-hint, +html.theme-light .model-viewer-data { + color: #3c3836; +} +html.theme-light .model-viewer-data { + background: rgba(251, 241, 199, 0.85); + border-color: #d5c4a1; +} +html.theme-light .model-viewer-status.error { + color: #9d0006; +} +html.theme-light .model-viewer-progress { + background: #d5c4a1; +} +html.theme-light .model-viewer-progress-fill { + background: #83a598; +} + +/* ---------- Bildunterschriften (Gruvbox) ---------- */ +#content figcaption { + font-size: 0.85em; + font-style: italic; + color: var(--text-menu); + text-align: center; + margin-top: 8px; + padding: 4px 12px; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + display: inline-block; +} + +.hljs { + background: #282828; + color: #ebdbb2; +} + +.hljs-comment, +.hljs-quote { + color: #928374; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-subst { + color: #fb4934; +} + +.hljs-number, +.hljs-literal, +.hljs-variable, +.hljs-template-variable, +.hljs-tag .hljs-attr { + color: #d3869b; +} + +.hljs-string, +.hljs-doctag { + color: #b8bb26; +} + +.hljs-title, +.hljs-section, +.hljs-selector-id { + color: #fe8019; +} + +.hljs-type, +.hljs-class .hljs-title, +.hljs-attribute { + color: #fabd2f; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-meta, +.hljs-deletion, +.hljs-addition { + color: #d3869b; +} + +.hljs-built_in, +.hljs-builtin-name, +.hljs-params { + color: #8ec07c; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} +/* ---------- Light mode: Gruvbox Light highlighter ---------- */ +html.theme-light .hljs, +html.theme-light pre code.hljs { + background: #fbf1c7 !important; + color: #3c3836; +} + +html.theme-light .hljs-comment, +html.theme-light .hljs-quote { + color: #928374; +} + +html.theme-light .hljs-keyword, +html.theme-light .hljs-selector-tag, +html.theme-light .hljs-subst { + color: #9d0006; +} + +html.theme-light .hljs-number, +html.theme-light .hljs-literal, +html.theme-light .hljs-variable, +html.theme-light .hljs-template-variable, +html.theme-light .hljs-tag .hljs-attr { + color: #8f3f71; +} + +html.theme-light .hljs-string, +html.theme-light .hljs-doctag { + color: #79740e; +} + +html.theme-light .hljs-title, +html.theme-light .hljs-section, +html.theme-light .hljs-selector-id { + color: #af3a03; +} + +html.theme-light .hljs-type, +html.theme-light .hljs-class .hljs-title, +html.theme-light .hljs-attribute { + color: #b57614; +} + +html.theme-light .hljs-symbol, +html.theme-light .hljs-bullet, +html.theme-light .hljs-link, +html.theme-light .hljs-meta, +html.theme-light .hljs-deletion, +html.theme-light .hljs-addition { + color: #8f3f71; +} + +html.theme-light .hljs-built_in, +html.theme-light .hljs-builtin-name, +html.theme-light .hljs-params { + color: #427b58; +} + +html.theme-light .hljs-regexp, +html.theme-light .hljs-operator, +html.theme-light .hljs-selector-attr, +html.theme-light .hljs-selector-pseudo, +html.theme-light .hljs-selector-class, +html.theme-light .hljs-template-tag { + color: #8f3f71; +} + +html.theme-light .hljs-name, +html.theme-light .hljs-tag { + color: #076678; +} + +html.theme-light .hljs-meta .hljs-string { + color: #79740e; +} +/* ---------- Admonitions (Trilium-style, gefüllt) ---------- */ +.admonition { + --accent-color: var(--background-highlight); + --admonition-bg: var(--background-secondary); + border: 1px solid var(--accent-color); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15); + background: var(--admonition-bg); + border-radius: 0.5em; + padding: 1em; + padding-inline-start: 2.5em; + margin: 1.25em 0; + position: relative; + overflow: hidden; +} + +html.theme-dark .admonition.note { --admonition-bg: rgba(105, 199, 255, 0.16); } +html.theme-dark .admonition.tip { --admonition-bg: rgba(64, 192, 37, 0.14); } +html.theme-dark .admonition.important { --admonition-bg: rgba(152, 57, 247, 0.18); } +html.theme-dark .admonition.caution { --admonition-bg: rgba(255, 46, 46, 0.16); } +html.theme-dark .admonition.warning { --admonition-bg: rgba(226, 170, 3, 0.14); } +html.theme-dark .admonition { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); } + +html.theme-light .admonition.note { --admonition-bg: rgba(105, 199, 255, 0.22); } +html.theme-light .admonition.tip { --admonition-bg: rgba(64, 192, 37, 0.16); } +html.theme-light .admonition.important { --admonition-bg: rgba(152, 57, 247, 0.15); } +html.theme-light .admonition.caution { --admonition-bg: rgba(255, 46, 46, 0.15); } +html.theme-light .admonition.warning { --admonition-bg: rgba(226, 170, 3, 0.20); } + +.admonition p:last-child { + margin-bottom: 0; +} + +.admonition p, +.admonition h2 { + margin-top: 0; +} + +.admonition.note { --accent-color: #69c7ff; } +.admonition.tip { --accent-color: #40c025; } +.admonition.important { --accent-color: #9839f7; } +.admonition.caution { --accent-color: #ff2e2e; } +.admonition.warning { --accent-color: #e2aa03; } + +.admonition::before { + color: var(--accent-color); + font-family: boxicons !important; + position: absolute; + top: 1em; + inset-inline-start: 1em; +} + +.admonition.note::before { content: "\eb21"; } +.admonition.tip::before { content: "\ea0d"; } +.admonition.important::before { content: "\ea7c"; } +.admonition.caution::before { content: "\eac7"; } +.admonition.warning::before { content: "\eac5"; } +/* ---------- Tables (Gruvbox, theme-aware) ---------- */ +html.theme-dark { + --table-header-bg: rgba(131, 165, 152, 0.30); + --table-header-text: #fbf1c7; + --table-header-border: rgba(131, 165, 152, 0.6); + --table-stripe: rgba(255, 255, 255, 0.04); + --table-hover: rgba(131, 165, 152, 0.16); + --table-rowlabel-bg: rgba(255, 255, 255, 0.05); + --table-rowlabel-text: #ebdbb2; +} + +html.theme-light { + --table-header-bg: rgba(7, 102, 120, 0.20); + --table-header-text: #282828; + --table-header-border: rgba(7, 102, 120, 0.45); + --table-stripe: rgba(0, 0, 0, 0.04); + --table-hover: rgba(7, 102, 120, 0.12); + --table-rowlabel-bg: rgba(0, 0, 0, 0.05); + --table-rowlabel-text: #3c3836; +} + +.ck-content table, +#content table { + border-collapse: separate; + border-spacing: 0; + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow: hidden; + margin: 1em 0; +} + +.ck-content table th, +.ck-content table td, +#content table th, +#content table td { + border: none; + border-bottom: 1px solid var(--background-highlight); + border-right: 1px solid var(--background-highlight); + padding: 8px 12px; + text-align: left; + background-color: transparent !important; +} + +.ck-content table th:last-child, +.ck-content table td:last-child, +#content table th:last-child, +#content table td:last-child { + border-right: none; +} + +.ck-content table tr:last-child td, +#content table tr:last-child td { + border-bottom: none; +} + +.ck-content table thead th, +#content table thead th { + background-color: var(--table-header-bg) !important; + color: var(--table-header-text); + font-weight: 700; + border-bottom: 2px solid var(--table-header-border); +} + +.ck-content table tbody td:first-child, +#content table tbody td:first-child { + background-color: var(--table-rowlabel-bg) !important; + color: var(--table-rowlabel-text); + font-weight: 600; + white-space: nowrap; +} + +.ck-content table tbody tr:nth-child(even) td:not(:first-child), +#content table tbody tr:nth-child(even) td:not(:first-child) { + background-color: var(--table-stripe) !important; +} + +.ck-content table tbody tr:hover td, +#content table tbody tr:hover td { + background-color: rgba(254, 128, 25, 0.07) !important; +} + +.ck-content table .col-hover, +#content table .col-hover { + background-color: rgba(254, 128, 25, 0.07) !important; +} + +.ck-content table tbody tr:hover td.col-hover, +.ck-content table thead th.col-hover, +#content table tbody tr:hover td.col-hover, +#content table thead th.col-hover { + background-color: rgba(254, 128, 25, 0.14) !important; +} +/* ---------- Category subcategories ---------- */ +.blog-subcategories { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin: 0 0 1.25em; +} + +.blog-subcategory { + display: inline-flex; + align-items: center; + gap: 6px; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + padding: 4px 12px; + color: var(--text-heading); + text-decoration: none; + font-weight: 600; + transition: background-color 150ms ease, border-color 150ms ease; +} + +.blog-subcategory i { + color: var(--text-link); +} + +.blog-subcategory:hover { + background: var(--background-highlight); + border-color: var(--text-link); + color: var(--text-heading); + text-decoration: none; +} +/* ---------- Digital Garden note table ---------- */ +.blog-garden-table { + width: 100%; +} + +.blog-garden-table tbody td:first-child { + background: transparent !important; + font-weight: normal; +} + +.note-type { + display: inline-block; + font-size: 0.8em; + padding: 2px 10px; + border-radius: 8px; + background: var(--background-highlight); + color: var(--text-heading); + font-weight: 600; + text-transform: capitalize; + white-space: nowrap; +} +/* ---------- Digital Garden rows: clickable + green hover ---------- */ +.blog-garden-table tbody tr { + cursor: pointer; +} + +#content .blog-garden-table tbody tr:hover td, +#content .blog-garden-table .col-hover { + background-color: rgba(184, 187, 38, 0.12) !important; +} + +#content .blog-garden-table tbody tr:hover td.col-hover { + background-color: rgba(184, 187, 38, 0.20) !important; +} +.note-state { + display: inline-flex; + align-items: center; + gap: 5px; + font-size: 0.8em; + padding: 2px 10px; + border-radius: 8px; + background: rgba(184, 187, 38, 0.18); + color: var(--text-heading); + font-weight: 600; + white-space: nowrap; +} + +.note-state i { + color: #b8bb26; +} + +.note-state.state-draft { + background: rgba(146, 131, 116, 0.22); +} + +.note-state.state-draft i { + color: #928374; +} + +.note-state.state-review { + background: rgba(131, 165, 152, 0.25); +} + +.note-state.state-review i { + color: #83a598; +} + +.note-state.state-unknown { + background: rgba(251, 73, 52, 0.20); +} + +.note-state.state-unknown i { + color: #fb4934; +} + +/* ---------- Peppige Garden-Badges (dark) ---------- */ +html.theme-dark .note-state { + background: rgba(184, 187, 38, 0.45); + border: 1px solid #b8bb26; + color: #282828; +} +html.theme-dark .note-state i { + color: #282828; +} +html.theme-dark .note-state.state-draft { + background: rgba(251, 73, 52, 0.85); + border-color: #ff6a5e; + color: #1d2021; +} +html.theme-dark .note-state.state-draft i { + color: #1d2021; +} +html.theme-dark .note-state.state-review { + background: rgba(131, 165, 152, 0.85); + border-color: #a3c7bb; + color: #1d2021; +} +html.theme-dark .note-state.state-review i { + color: #1d2021; +} +html.theme-dark .note-state.state-unknown { + background: rgba(254, 128, 25, 0.85); + border-color: #ffa45e; + color: #1d2021; +} +html.theme-dark .note-state.state-unknown i { + color: #1d2021; +} + +/* ---------- Peppige Garden-Badges (light) ---------- */ +html.theme-light .note-state { + background: rgba(121, 116, 14, 0.85); + border: 1px solid #79740e; + color: #f9f5d7; +} +html.theme-light .note-state i { + color: #f9f5d7; +} +html.theme-light .note-state.state-draft { + background: rgba(204, 36, 29, 0.90); + border-color: #9d0006; + color: #f9f5d7; +} +html.theme-light .note-state.state-draft i { + color: #f9f5d7; +} +html.theme-light .note-state.state-review { + background: rgba(69, 133, 136, 0.90); + border-color: #427b58; + color: #f9f5d7; +} +html.theme-light .note-state.state-review i { + color: #f9f5d7; +} +html.theme-light .note-state.state-unknown { + background: rgba(175, 58, 3, 0.90); + border-color: #af3a03; + color: #f9f5d7; +} +html.theme-light .note-state.state-unknown i { + color: #f9f5d7; +} +/* ---------- Code notes: always Gruvbox dark like code boxes ---------- */ +#content.type-code pre { + background-color: #282828 !important; + color: #ebdbb2; + border: 1px solid #504945; + border-radius: 8px; + padding: 1em; + margin: 1em 0; +} + +#content.type-code code { + background-color: transparent !important; + color: #ebdbb2; + border: 0; +} + +html.theme-light #content.type-code pre { + background-color: #fbf1c7 !important; + color: #3c3836; + border-color: #d5c4a1; +} + +html.theme-light #content.type-code code { + color: #3c3836; +} +/* ---------- Code: line numbers + copy button ---------- */ +pre.code-processed { + position: relative; + display: flex; + align-items: flex-start; + line-height: 1.6; +} + +pre.code-processed .code-wrap { + flex: 1; + min-width: 0; + overflow-x: auto; + border-radius: 8px; +} + +pre.code-processed .code-wrap code { + display: block; + line-height: inherit; + padding: 0; + margin: 0; +} + +pre.code-processed .code-lines { + flex-shrink: 0; + user-select: none; + text-align: right; + padding: 0 12px 0 0; + margin: 0 12px 0 0; + border-right: 1px solid var(--background-highlight); + color: var(--text-menu); + white-space: pre; + font-family: "JetBrains Mono", Consolas, monospace; + font-size: 1em; + line-height: inherit; +} + +pre.code-processed .code-copy-btn, +.mermaid-source pre .code-copy-btn { + position: absolute; + top: 6px; + right: 6px; + z-index: 2; + font-size: 0.75em; + padding: 2px 10px; + border-radius: 6px; + border: 1px solid var(--background-highlight); + background: var(--background-secondary); + color: var(--text-heading); + cursor: pointer; + opacity: 0.6; + transition: opacity 150ms ease; +} + +pre.code-processed:hover .code-copy-btn, +.mermaid-source pre:hover .code-copy-btn { + opacity: 1; +} + +pre.code-processed .code-copy-btn:hover, +.mermaid-source pre .code-copy-btn:hover { + border-color: var(--text-link); + opacity: 1; +} +/* ---------- highlight.js line numbers ---------- */ +#content .hljs-ln { + border-collapse: collapse; + border: none !important; + box-shadow: none; + border-radius: 8px; + margin: 0; + width: auto; + line-height: 1.4; +} + +#content .hljs-ln td, +#content .hljs-ln th { + border: none !important; + background-color: transparent !important; + padding: 0; +} + +#content .hljs-ln tbody td:first-child, +#content .hljs-ln thead th:first-child { + background-color: transparent !important; +} + +#content .hljs-ln tbody tr:nth-child(even) td { + background-color: transparent !important; +} + +#content .hljs-ln .col-hover { + background-color: transparent !important; +} + +#content .hljs-ln tbody tr:hover td, +#content .hljs-ln tbody tr:hover td.col-hover { + background-color: rgba(254, 128, 25, 0.07) !important; +} + +html.theme-light #content .hljs-ln tbody tr:hover td, +html.theme-light #content .hljs-ln tbody tr:hover td.col-hover { + background-color: rgba(254, 128, 25, 0.08) !important; +} + +.hljs-ln-numbers { + user-select: none; + text-align: right; + padding-right: 12px !important; + padding-left: 4px; + border-right: 1px solid var(--background-highlight) !important; + color: var(--text-menu); + white-space: nowrap; + vertical-align: top; + font-family: "JetBrains Mono", Consolas, monospace; +} + +.hljs-ln-code { + padding-left: 12px !important; + white-space: pre; + vertical-align: top; +} +/* ---------- Scrollbars (Gruvbox) ---------- */ +::-webkit-scrollbar { + width: 12px; + height: 12px; +} + +::-webkit-scrollbar-track { + background: var(--scrollbar-track); +} + +::-webkit-scrollbar-thumb { + background: var(--scrollbar-thumb); + border-radius: 6px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--scrollbar-hover); +} + +* { + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); +} + +/* ---------- Code boxes: scrollbars ---------- */ +pre, +pre.code-processed .code-wrap, +.hljs-ln-code { + scrollbar-color: #504945 #1d2021; +} + +pre::-webkit-scrollbar-thumb, +pre.code-processed .code-wrap::-webkit-scrollbar-thumb, +.hljs-ln-code::-webkit-scrollbar-thumb { + background: #504945; +} + +pre::-webkit-scrollbar-thumb:hover, +pre.code-processed .code-wrap::-webkit-scrollbar-thumb:hover, +.hljs-ln-code::-webkit-scrollbar-thumb:hover { + background: #665c54; +} + +pre::-webkit-scrollbar-track, +pre.code-processed .code-wrap::-webkit-scrollbar-track, +.hljs-ln-code::-webkit-scrollbar-track { + background: #1d2021; +} + +html.theme-light pre, +html.theme-light pre.code-processed .code-wrap, +html.theme-light .hljs-ln-code { + scrollbar-color: #bdae93 #ebdbb2; +} + +html.theme-light pre::-webkit-scrollbar-thumb, +html.theme-light pre.code-processed .code-wrap::-webkit-scrollbar-thumb, +html.theme-light .hljs-ln-code::-webkit-scrollbar-thumb { + background: #bdae93; +} + +html.theme-light pre::-webkit-scrollbar-thumb:hover, +html.theme-light pre.code-processed .code-wrap::-webkit-scrollbar-thumb:hover, +html.theme-light .hljs-ln-code::-webkit-scrollbar-thumb:hover { + background: #d5c4a1; +} + +html.theme-light pre::-webkit-scrollbar-track, +html.theme-light pre.code-processed .code-wrap::-webkit-scrollbar-track, +html.theme-light .hljs-ln-code::-webkit-scrollbar-track { + background: #ebdbb2; +} + +/* ---------- Link icons / markers: internal links without arrow, external links keep a marker ---------- */ +#content a::after, +#content a::before, +#content-footer .navigation a::after, +#content-footer .navigation a::before, +a.next::after, +a.previous::before, +.bmc-btn::after, +.bmc-btn::before, +.bmc-powered::after, +.bmc-powered::before { + content: none !important; +} + +#content a[href^="http://"]:not([href^="https://YOUR-INSTANCE.example.com"])::after, +#content a[href^="https://"]:not([href^="https://YOUR-INSTANCE.example.com"])::after { + content: " ↗" !important; + display: inline-block; + margin-left: 3px; + font-size: 0.85em; + color: var(--text-link); +} + +/* inline text links (in paragraphs/lists): colour only */ +#content p a:not([class]), +#content li a:not([class]) { + color: var(--text-link); + text-decoration: none; + background: transparent; + border: 0; + padding: 0; + border-radius: 0; +} + +#content p a:not([class]):hover, +#content li a:not([class]):hover { + color: var(--text-heading); + background: transparent; +} + +/* action links as buttons (subtle tint, noticeable on hover) */ +.blog-pn { + padding: 6px 14px; + border: 1px solid rgba(131, 165, 152, 0.35); + border-radius: 8px; + background: rgba(131, 165, 152, 0.08); + transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease; +} + +html.theme-light .blog-pn { + border-color: rgba(7, 102, 120, 0.35); + background: rgba(7, 102, 120, 0.08); +} + +.blog-pn:hover { + background: rgba(131, 165, 152, 0.18); + border-color: #83a598; +} + +html.theme-light .blog-pn:hover { + background: rgba(7, 102, 120, 0.15); + border-color: #076678; +} + +/* ---------- Mermaid diagrams - Gruvbox, theme-following ---------- */ +/* + * The blog renders inline Mermaid diagrams with the default theme, so the + * generated SVG carries light-blue node fills that clash with Gruvbox. + * Override the SVG element colours here; the selectors hang off + * html.theme-dark / html.theme-light, so the diagrams follow the theme + * toggle automatically without re-rendering. + */ + +.mermaid { + margin: 1.25em auto; + overflow-x: auto; + background: transparent; +} + +.mermaid svg { + max-width: 100%; + height: auto; +} + +/* Text in node labels and titles */ +html.theme-dark .mermaid svg text, +html.theme-dark .mermaid svg tspan, +html.theme-dark .mermaid svg .nodeLabel, +html.theme-dark .mermaid svg .edgeLabel p { + fill: #ebdbb2 !important; + color: #ebdbb2 !important; +} + +html.theme-light .mermaid svg text, +html.theme-light .mermaid svg tspan, +html.theme-light .mermaid svg .nodeLabel, +html.theme-light .mermaid svg .edgeLabel p { + fill: #3c3836 !important; + color: #3c3836 !important; +} + +/* Graph/node title */ +html.theme-dark .mermaid svg .titleText text, +html.theme-dark .mermaid svg .node .label .nodeLabel { + fill: #fbf1c7 !important; + color: #fbf1c7 !important; +} + +html.theme-light .mermaid svg .titleText text, +html.theme-light .mermaid svg .node .label .nodeLabel { + fill: #282828 !important; + color: #282828 !important; +} + +/* Node shapes (rectangles, rounded boxes, ellipses, diamonds) */ +html.theme-dark .mermaid svg .node rect, +html.theme-dark .mermaid svg .node polygon, +html.theme-dark .mermaid svg .node circle, +html.theme-dark .mermaid svg .node ellipse, +html.theme-dark .mermaid svg .node path, +html.theme-dark .mermaid svg .cluster rect { + fill: #3c3836 !important; + stroke: #83a598 !important; +} + +html.theme-light .mermaid svg .node rect, +html.theme-light .mermaid svg .node polygon, +html.theme-light .mermaid svg .node circle, +html.theme-light .mermaid svg .node ellipse, +html.theme-light .mermaid svg .node path, +html.theme-light .mermaid svg .cluster rect { + fill: #ebdbb2 !important; + stroke: #076678 !important; +} + +/* Rounded corners on rectangular node boxes and subgraph clusters (8 px, like the blog cards) */ +html.theme-dark .mermaid svg .node rect, +html.theme-light .mermaid svg .node rect, +html.theme-dark .mermaid svg .cluster rect, +html.theme-light .mermaid svg .cluster rect { + rx: 8px !important; + ry: 8px !important; +} + +/* Edge lines: stroke only (a filled edge path would look like a polygon) */ +html.theme-dark .mermaid svg .edgePaths path { + fill: none !important; + stroke: #a89984 !important; +} + +html.theme-light .mermaid svg .edgePaths path { + fill: none !important; + stroke: #928374 !important; +} + +/* Arrowheads (markers): filled triangles */ +html.theme-dark .mermaid svg marker.flowchart-v2, +html.theme-dark .mermaid svg .arrowMarkerPath { + fill: #a89984 !important; + stroke: #a89984 !important; +} + +html.theme-light .mermaid svg marker.flowchart-v2, +html.theme-light .mermaid svg .arrowMarkerPath { + fill: #928374 !important; + stroke: #928374 !important; +} + +/* Edge labels: HTML text inside a foreignObject (div.labelBkg > span.edgeLabel); + the label panel background lives on the g.edgeLabel element itself */ +html.theme-dark .mermaid svg g.edgeLabel { + background: #282828 !important; + fill: #ebdbb2 !important; + color: #ebdbb2 !important; +} + +html.theme-dark .mermaid svg .edgeLabel .labelBkg { + fill: #282828 !important; + background: #282828 !important; + color: #ebdbb2 !important; +} + +html.theme-dark .mermaid svg .edgeLabel .labelBkg .edgeLabel { + fill: #ebdbb2 !important; + color: #ebdbb2 !important; + background: #282828 !important; +} + +html.theme-dark .mermaid svg .edgeLabel .labelBkg .edgeLabel p { + fill: #ebdbb2 !important; + color: #ebdbb2 !important; + background: #282828 !important; +} + +html.theme-light .mermaid svg g.edgeLabel { + background: #ebdbb2 !important; + fill: #3c3836 !important; + color: #3c3836 !important; +} + +html.theme-light .mermaid svg .edgeLabel .labelBkg { + fill: #ebdbb2 !important; + background: #ebdbb2 !important; + color: #3c3836 !important; +} + +html.theme-light .mermaid svg .edgeLabel .labelBkg .edgeLabel { + fill: #3c3836 !important; + color: #3c3836 !important; + background: #ebdbb2 !important; +} + +html.theme-light .mermaid svg .edgeLabel .labelBkg .edgeLabel p { + fill: #3c3836 !important; + color: #3c3836 !important; + background: #ebdbb2 !important; +} + +/* Subgraph cluster border + label */ +html.theme-dark .mermaid svg .cluster rect { + stroke: #504945 !important; + fill: rgba(40, 40, 40, 0.35) !important; +} + +html.theme-light .mermaid svg .cluster rect { + stroke: #d5c4a1 !important; + fill: rgba(235, 219, 178, 0.40) !important; +} + +html.theme-dark .mermaid svg .cluster .nodeLabel, +html.theme-dark .mermaid svg .cluster-label text { + fill: #a89984 !important; + color: #a89984 !important; +} + +html.theme-light .mermaid svg .cluster .nodeLabel, +html.theme-light .mermaid svg .cluster-label text { + fill: #504945 !important; + color: #504945 !important; +} +/* ---------- G-code / Zusatz-Scopes (name = G/M-Codes, attr = Parameter) ---------- */ +.hljs-name { color: #fabd2f; } +.hljs-attr { color: #83a598; } +html.theme-light .hljs-name { color: #076678; } +html.theme-light .hljs-attr { color: #427b58; } \ No newline at end of file diff --git a/theme/blog_share_theme_harbor.css b/theme/blog_share_theme_harbor.css new file mode 100644 index 0000000..08d4dc3 --- /dev/null +++ b/theme/blog_share_theme_harbor.css @@ -0,0 +1,1886 @@ +/* + * Harbor Share Theme for Richard's Blog (Trilium Public Share) + * Light: Harbor (paper #dfe4c4 / ink #1c2d28, accent #5e81ac) + * Dark: Harbordark (#1b1b1b / #efebdc, accent #e75a50) + * Based on https://github.com/HANCORE-linux/omarchy-harbor-theme (MIT) + */ + +html.theme-light { + --background-primary: #dfe4c4; + --background-secondary: #d0d6b4; + --background-highlight: #c3c9a6; + --background-active: #5e81ac; + --blog-card-bg: #d0d6b4; + --scrollbar-thumb: #c3c9a6; + --scrollbar-hover: #b3ba96; + --scrollbar-track: #d0d6b4; + --text-primary: #1c2d28; + --text-heading: #1c2d28; + --text-menu: #556753; + --text-link: #4c6c94; + --text-menu-active: #dfe4c4; + color-scheme: light; +} + +html.theme-dark { + --background-primary: #1b1b1b; + --background-secondary: #232323; + --background-highlight: #2e2e2e; + --background-active: #e75a50; + --blog-card-bg: #262626; + --scrollbar-thumb: #2e2e2e; + --scrollbar-hover: #3f3f3f; + --scrollbar-track: #1b1b1b; + --text-primary: #efebdc; + --text-heading: #efebdc; + --text-menu: #a99b7a; + --text-link: #e58980; + --text-menu-active: #1b1b1b; + color-scheme: dark; +} + +body { + font-family: "Inter", "Montserrat", "Lucida Grande", "Lucida Sans Unicode", arial, sans-serif; +} + +/* ---------- Header: Logo durch Laptop-Emoji ---------- */ +#header-logo img { + display: none; +} + +#header-logo::before { + content: "💻"; + font-size: 1.5em; + line-height: 1; + margin-right: 8px; + display: inline-block; + vertical-align: middle; +} + +/* ---------- Buy Me a Coffee (original, lokal) ---------- */ +@font-face { + font-family: "Cookie"; + src: url(/api/notes/__COOKIE_FONT_ID__/download) format("woff2"); + font-weight: 400; + font-display: swap; +} + +#bmc-links { + margin-top: auto; + padding: 8px 25px 4px; + background: var(--background-secondary); + display: flex; + flex-direction: column; + gap: 2px; +} + +.bmc-link { + display: flex; + align-items: center; + gap: 8px; + padding: 4px 6px 4px 24px; + border-radius: 6px; + color: var(--text-heading); + text-decoration: none; + font-size: 0.9em; + transition: background-color 150ms ease, color 150ms ease; +} + +.bmc-link:hover { + background: var(--background-highlight); + color: var(--text-heading); + text-decoration: none; +} + +.bmc-link .tn-icon { + color: var(--text-link); +} + +/* ---------- Menu: wie Footer-Links gestalten ---------- */ +#menu a { + color: var(--text-heading); + gap: 8px; + font-size: 0.9em; + padding: 4px 6px; + border-color: transparent; + transition: background-color 150ms ease, color 150ms ease; +} + +#menu a:hover { + background: var(--background-highlight); + color: var(--text-heading); + border-color: transparent; + text-decoration: none; +} + +#menu a.active { + background: var(--background-active); + color: var(--background-secondary); + border-color: transparent; +} + +#menu .tn-icon { + color: var(--text-link); +} + +#bmc-wrap { + padding: 8px 14px 14px; + background: var(--background-secondary); + border-top: 1px solid var(--background-highlight); +} + +.bmc-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + width: 100%; + box-sizing: border-box; + padding: 6px 12px 8px; + border-radius: 8px; + background: #fabd2f; + color: #1c2d28; + border: 2px solid #1c2d28; + font-family: "Cookie", "Brush Script MT", cursive; + font-size: 1.4em; + line-height: 1.1; + text-decoration: none; + transition: background-color 150ms ease, transform 150ms ease; +} + +.bmc-btn:hover { + background: #dc8164; + color: #1c2d28; + text-decoration: none; + transform: translateY(-1px); +} + +.bmc-btn .bmc-emoji { + font-size: 1.15em; +} + +.bmc-copyright { + margin-top: 8px; + font-size: 0.75em; + color: var(--text-menu); + display: flex; + align-items: center; + justify-content: center; + gap: 4px; + flex-wrap: wrap; +} + +.bmc-powered { + display: inline-flex; + align-items: center; + gap: 3px; + color: var(--text-menu); + text-decoration: none; + transition: color 150ms ease; +} + +.bmc-powered:hover { + color: var(--text-link); + text-decoration: none; +} + +.powered-logo { + width: 1em; + height: 1em; + display: inline-block; +} + +/* ---------- Reading time ---------- */ +.reading-time { + font-size: 0.8em; + color: var(--text-menu); + margin: -0.9em 0 1.25em; +} + +/* ---------- Blog pagination ---------- */ +.blog-pagination { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin: 1.5em 0 0; + padding-top: 1em; + border-top: 1px solid var(--background-highlight); +} + +.blog-pagination .blog-page-num { + font-size: 0.85em; + color: var(--text-menu); +} + +/* ---------- Share footer navigation (built-in prev/next) ausblenden ---------- */ +#content-footer .navigation { + display: none; +} + +/* ---------- Prev/Next ---------- */ +.blog-prevnext { + display: flex; + justify-content: space-between; + gap: 12px; + margin: 1.5em 0 0; + padding-top: 1em; + border-top: 1px solid var(--background-highlight); +} + +.blog-pn { + display: flex; + flex-direction: column; + gap: 2px; + max-width: 45%; + color: var(--text-heading); + text-decoration: none; + transition: color 150ms ease; +} + +.blog-pn.next { + margin-left: auto; + align-items: flex-end; + text-align: right; +} + +.blog-pn-label { + font-size: 0.72em; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--text-menu); +} + +.blog-pn:hover { + color: var(--text-link); + text-decoration: none; +} + +.blog-pn.empty { + display: none; +} + +/* ---------- Search ---------- */ +.blog-search { + margin: 0.5em 0 1em; +} + +.blog-search-input { + width: 100%; + box-sizing: border-box; + padding: 10px 14px; + border-radius: 8px; + border: 1px solid var(--background-highlight); + background: var(--background-secondary); + color: var(--text-heading); + font-size: 1em; +} + +.blog-search-input:focus { + outline: none; + border-color: var(--text-link); +} + +.blog-search-list { + list-style: none; + padding: 0; + margin: 1em 0 0; +} + +.blog-search-hit { + display: flex; + flex-direction: column; + gap: 2px; + padding: 8px 12px; + border-radius: 8px; + border: 1px solid var(--background-highlight); + background: var(--blog-card-bg); + color: var(--text-heading); + text-decoration: none; + margin-bottom: 8px; + transition: border-color 150ms ease; +} + +.blog-search-hit:hover { + border-color: var(--text-link); + text-decoration: none; +} + +.blog-search-path { + font-size: 0.8em; + color: var(--text-menu); +} + +.blog-search-none { + color: var(--text-menu); +} + +/* ---------- Header-Suche (ersetzt eingebaute) ---------- */ +.search-item { + position: relative; +} + +.blog-search-header-input { + flex: 1; + min-width: 0; + padding: 6px 10px 6px 32px; + border-radius: 6px; + border: 1px solid rgba(119, 131, 138, 0.55); + background: rgba(119, 131, 138, 0.10); + color: var(--text-heading); + font-size: 0.9em; + transition: border-color 150ms ease, box-shadow 150ms ease; +} + +html.theme-light .blog-search-header-input { + border-color: #4c6c94; + background: rgba(76, 108, 148, 0.10); +} + +.blog-search-header-input:focus { + outline: none; + border-color: #77838a; + box-shadow: 0 0 0 2px rgba(119, 131, 138, 0.20); +} + +html.theme-light .blog-search-header-input:focus { + border-color: #4c6c94; + box-shadow: 0 0 0 2px rgba(76, 108, 148, 0.15); +} + +.search-item .search-icon { + color: rgba(119, 131, 138, 0.85); +} + +html.theme-light .search-item .search-icon { + color: #4c6c94; +} + +.tn-image { + width: 18px; + height: 18px; + border-radius: 4px; + flex-shrink: 0; + vertical-align: middle; +} + +.tn-image-svg { + color: var(--text-link); +} + +.title-image { + width: 34px; + height: 34px; + border-radius: 6px; + vertical-align: middle; + margin-right: 10px; +} + +.note-fallback { + margin: 1em 0; + overflow: hidden; +} + +.note-fallback-link { + font-size: 0.9em; +} + +.mermaid-fallback { + margin: 1em 0; +} + +.mermaid-render { + margin: 1em 0; + padding: 14px; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow-x: auto; +} + +.mermaid-render svg { + max-width: 100%; + height: auto; +} + +.mermaid-source { + margin: 12px 0 0; + text-align: center; +} + +.mermaid-source summary { + cursor: pointer; + font-size: 0.85em; + color: var(--text-menu); + user-select: none; + padding: 4px 10px; + border: 1px solid var(--background-highlight); + border-radius: 6px; + display: inline-block; + background: var(--background-secondary); +} + +.mermaid-source summary:hover { + color: var(--text-heading); + border-color: var(--text-link); +} + +.mermaid-source pre { + width: min(100%, 820px); + margin: 8px auto 0; + text-align: left; + position: relative; + overflow: hidden; +} + +#content .mermaid-source .hljs-ln { + width: 100%; +} + +/* ---------- Rendered widgets: mind map + excalidraw ---------- */ +.mindmap-render, +.excalidraw-render { + margin: 1em 0; + padding: 14px; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow-x: auto; +} + +.mindmap-svg { + display: block; + width: 100%; + height: auto; +} + +.excalidraw-svg { + display: block; + max-width: 100%; + height: auto; +} + +.mindmap-render svg text { + user-select: none; +} + +.blog-search-overlay { + display: none; + position: absolute; + top: calc(100% + 4px); + left: 0; + right: 0; + z-index: 50; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow: hidden; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); +} + +.blog-search-overlay.open { + display: block; +} + +.blog-search-overlay-hit { + display: flex; + flex-direction: column; + gap: 1px; + padding: 7px 10px; + color: var(--text-heading); + text-decoration: none; + font-size: 0.85em; + border-bottom: 1px solid var(--background-highlight); +} + +.blog-search-overlay-hit:last-child { + border-bottom: none; +} + +.blog-search-overlay-hit:hover { + background: var(--background-highlight); + text-decoration: none; +} + +.blog-search-overlay-hit .s { + font-size: 0.75em; + color: var(--text-menu); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.blog-search-overlay .blog-search-none { + padding: 8px 10px; + font-size: 0.85em; +} + +#main { + max-width: min(92vw, 1200px); +} + +#site-header { + padding-bottom: 10px; +} + +#title { + font-family: "JetBrains Mono", "Montserrat", monospace; + letter-spacing: -0.02em; +} + +body.is-garden #title { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +body.is-garden #title .note-state { + margin-left: auto; + flex-shrink: 0; +} + +body.is-garden #content h1#title { + background-color: rgba(169, 155, 122, 0.30) !important; + border-bottom-color: rgba(169, 155, 122, 0.60) !important; +} + +html.theme-light body.is-garden #content h1#title { + background-color: rgba(85, 103, 83, 0.15) !important; + border-bottom-color: rgba(85, 103, 83, 0.40) !important; +} + +/* ---------- Blog index (generated article list) ---------- */ +.blog-post { + padding: 1.2em 1.4em; + margin-bottom: 1.25em; + border: 1px solid var(--background-highlight); + border-radius: 10px; + background: var(--blog-card-bg); + transition: border-color 150ms ease, box-shadow 150ms ease; + cursor: pointer; +} + +.blog-post:last-child { + margin-bottom: 0; +} + +.blog-post:hover { + border-color: var(--text-link); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18); +} + +#content .blog-post:first-of-type { + margin-top: 1.5em; +} + +/* ---------- Blog post thumbnails (Bild links, Teaser rechts) ---------- */ +.blog-post-inner { + display: flex; + gap: 16px; + align-items: stretch; +} + +.blog-thumb-link { + flex: 0 0 auto; + width: min(256px, 35%); + text-decoration: none; +} + +.blog-thumb { + display: block; + width: 100%; + height: 100%; + max-height: 256px; + object-fit: cover; + border-radius: 8px; + border: 1px solid var(--background-highlight); +} + +.blog-post-body { + flex: 1; + min-width: 0; +} + +.blog-post-title { + margin: 0 0 0.25em; +} + +.blog-post-title a { + color: var(--text-heading); + text-decoration: none; + transition: color 150ms ease; +} + +.blog-post-title a:hover { + color: var(--text-link); + text-decoration: none; +} + +.blog-post-meta { + display: flex; + gap: 12px; + font-size: 0.85em; + color: var(--text-menu); + margin-bottom: 0.5em; +} + +.blog-post-date { + font-variant-numeric: tabular-nums; + opacity: 0.85; +} + +.blog-post-category { + background: var(--background-highlight); + border-radius: 8px; + padding: 1px 10px; + color: var(--text-heading); + font-weight: 600; +} + +.blog-post-summary { + margin: 0 0 0.5em; + color: var(--text-primary); +} + +.blog-post-tags { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.tag { + font-size: 0.78em; + color: var(--text-link); + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + padding: 1px 8px; +} + +a.tag { + text-decoration: none; + transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease; +} + +a.tag:hover { + background: var(--background-highlight); + border-color: var(--text-link); + color: var(--text-heading); + text-decoration: none; +} + +/* ---------- Article meta (date/category on individual pages) ---------- */ +.article-meta { + display: flex; + gap: 12px; + font-size: 0.9em; + color: var(--text-menu); + margin-bottom: 1em; + padding-bottom: 1em; + border-bottom: 1px solid var(--background-highlight); +} + +/* ---------- Headings (h2-h6) - Harbor header boxes ---------- */ +html.theme-dark { + --header-h2-bg: rgba(231, 90, 80, 0.30); + --header-h2-border: rgba(231, 90, 80, 0.6); + --header-h3-bg: rgba(169, 155, 122, 0.25); + --header-h3-border: rgba(169, 155, 122, 0.6); + --header-h4-bg: rgba(225, 206, 152, 0.22); + --header-h4-border: rgba(225, 206, 152, 0.55); + --header-h5-bg: rgba(119, 131, 138, 0.25); + --header-h5-border: rgba(119, 131, 138, 0.6); + --header-h6-bg: rgba(229, 137, 128, 0.25); + --header-h6-border: rgba(229, 137, 128, 0.6); + --header-h1-bg: rgba(244, 67, 54, 0.30); + --header-h1-border: rgba(244, 67, 54, 0.6); +} + +html.theme-light { + --header-h2-bg: rgba(94, 129, 172, 0.18); + --header-h2-border: rgba(94, 129, 172, 0.45); + --header-h3-bg: rgba(85, 103, 83, 0.14); + --header-h3-border: rgba(85, 103, 83, 0.38); + --header-h4-bg: rgba(220, 129, 100, 0.14); + --header-h4-border: rgba(220, 129, 100, 0.38); + --header-h5-bg: rgba(138, 91, 129, 0.12); + --header-h5-border: rgba(138, 91, 129, 0.35); + --header-h6-bg: rgba(61, 114, 125, 0.12); + --header-h6-border: rgba(61, 114, 125, 0.35); + --header-h1-bg: rgba(177, 71, 82, 0.14); + --header-h1-border: rgba(177, 71, 82, 0.40); +} + +#content h1 { + background-color: var(--header-h1-bg); + border-bottom: 2px solid var(--header-h1-border); + border-radius: 4px; + padding: 0.3em 0.4em; + font-size: 1.6em; + font-weight: 700; + margin-top: 1.5em; + margin-bottom: 1.25em; +} + +#content h2 { + background-color: var(--header-h2-bg); + border-bottom: 2px solid var(--header-h2-border); + border-radius: 4px; + padding: 0.25em 0.4em; +} + +#content h3 { + background-color: var(--header-h3-bg); + border-bottom: 2px solid var(--header-h3-border); + border-radius: 4px; + padding: 0.2em 0.35em; +} + +#content h4 { + background-color: var(--header-h4-bg); + border-bottom: 2px solid var(--header-h4-border); + border-radius: 4px; + padding: 0.2em 0.35em; +} + +#content h5 { + background-color: var(--header-h5-bg); + border-bottom: 2px solid var(--header-h5-border); + border-radius: 4px; + padding: 0.2em 0.35em; +} + +#content h6 { + background-color: var(--header-h6-bg); + border-bottom: 2px solid var(--header-h6-border); + border-radius: 4px; + padding: 0.2em 0.35em; +} + +#childLinks { + display: none; +} + +#index { + display: none; +} + +/* ---------- Code blocks - Harbordark (always, also in light mode) ---------- */ +.ck-content pre, +#content pre { + background-color: #222222; + color: #efebdc; + border: 1px solid #2e2e2e; + border-radius: 8px; +} + +.ck-content code, +#content code { + background-color: #2a2a2a; + color: #efebdc; + border-color: #3f3f3f; + border-radius: 8px; + padding: 0.1em 0.35em; +} + +html.theme-light .ck-content pre, +html.theme-light #content pre { + background-color: #e8ecd0; + color: #1c2d28; + border-color: #c3c9a6; +} + +html.theme-light .ck-content code, +html.theme-light #content code { + background-color: #cdd3b0; + color: #1c2d28; + border-color: #b3ba96; +} + +/* ---------- Eingebettete Bilder: Radius wie Code-Blöcke (8px) ---------- */ +#content figure.image { + margin: 1.25em auto; +} + +#content figure img, +#content img:not(.blog-thumb) { + border-radius: 8px; +} + +/* ---------- 3D model viewer (STL / STEP) ---------- */ +.model-viewer { + position: relative; + box-sizing: border-box; + width: calc(100vw - 24px); + margin: 1em 0; + margin-left: calc(50% - (100vw - 24px) / 2); + background: #1b1b1b; + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow: hidden; +} + +.model-viewer.model-viewer-inline { + width: 100%; + margin-left: 0; +} + +.model-viewer-data { + position: absolute; + top: 8px; + right: 10px; + z-index: 3; + display: none; + font-size: 0.75em; + color: #a99b7a; + background: rgba(27, 27, 27, 0.85); + border: 1px solid #2e2e2e; + border-radius: 6px; + padding: 2px 10px; + font-variant-numeric: tabular-nums; + pointer-events: none; +} + +.model-viewer-canvas { + position: relative; + width: 100%; + height: min(70vh, 900px); + min-height: 420px; +} + +.model-viewer-status { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + padding: 48px; + box-sizing: border-box; + color: #a99b7a; + font-size: 0.9em; +} + +.model-viewer-status.error { + color: #F44336; +} + +.model-viewer-progress { + position: absolute; + left: 0; + right: 0; + bottom: 40px; + height: 6px; + width: min(60%, 480px); + margin: 0 auto; + background: #2a2a2a; + border-radius: 3px; + overflow: hidden; +} + +.model-viewer-progress-fill { + height: 100%; + width: 0; + background: #E1CE98; + border-radius: 3px; + transition: width 150ms ease; +} + +.model-viewer-progress-fill.indeterminate { + width: 40%; + animation: model-progress 1.1s ease-in-out infinite; +} + +@keyframes model-progress { + 0% { transform: translateX(-100%); } + 100% { transform: translateX(250%); } +} + +.model-viewer-hint { + position: absolute; + top: 8px; + left: 10px; + font-size: 0.75em; + color: #a99b7a; + z-index: 2; + pointer-events: none; +} + +.model-viewer-caption { + font-size: 0.85em; + font-style: italic; + color: var(--text-menu); + text-align: center; + padding: 4px 12px; + background: var(--background-secondary); + border-top: 1px solid var(--background-highlight); +} + +.model-viewer canvas { + display: block; + width: 100%; + height: 100%; +} + +/* ---------- 3D-Viewer: theme-bewusste Overlays ---------- */ +html.theme-light .model-viewer { + background: #e8ecd0; +} +html.theme-light .model-viewer-status, +html.theme-light .model-viewer-hint, +html.theme-light .model-viewer-data { + color: #1c2d28; +} +html.theme-light .model-viewer-data { + background: rgba(223, 228, 196, 0.85); + border-color: #c3c9a6; +} +html.theme-light .model-viewer-status.error { + color: #b14752; +} +html.theme-light .model-viewer-progress { + background: #c3c9a6; +} +html.theme-light .model-viewer-progress-fill { + background: #5e81ac; +} + +/* ---------- Bildunterschriften (Harbor) ---------- */ +#content figcaption { + font-size: 0.85em; + font-style: italic; + color: var(--text-menu); + text-align: center; + margin-top: 8px; + padding: 4px 12px; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + display: inline-block; +} + +.hljs { + background: #222222; + color: #efebdc; +} + +.hljs-comment, +.hljs-quote { + color: #817f68; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-subst { + color: #F44336; +} + +.hljs-number, +.hljs-literal, +.hljs-variable, +.hljs-template-variable, +.hljs-tag .hljs-attr { + color: #e58980; +} + +.hljs-string, +.hljs-doctag { + color: #a99b7a; +} + +.hljs-title, +.hljs-section, +.hljs-selector-id { + color: #E1CE98; +} + +.hljs-type, +.hljs-class .hljs-title, +.hljs-attribute { + color: #77838a; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-meta, +.hljs-deletion, +.hljs-addition { + color: #e58980; +} + +.hljs-built_in, +.hljs-builtin-name, +.hljs-params { + color: #77838a; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} +/* ---------- Light mode: Harbor light highlighter ---------- */ +html.theme-light .hljs, +html.theme-light pre code.hljs { + background: #e8ecd0 !important; + color: #1c2d28; +} + +html.theme-light .hljs-comment, +html.theme-light .hljs-quote { + color: #7d8794; +} + +html.theme-light .hljs-keyword, +html.theme-light .hljs-selector-tag, +html.theme-light .hljs-subst { + color: #b14752; +} + +html.theme-light .hljs-number, +html.theme-light .hljs-literal, +html.theme-light .hljs-variable, +html.theme-light .hljs-template-variable, +html.theme-light .hljs-tag .hljs-attr { + color: #8a5b81; +} + +html.theme-light .hljs-string, +html.theme-light .hljs-doctag { + color: #556753; +} + +html.theme-light .hljs-title, +html.theme-light .hljs-section, +html.theme-light .hljs-selector-id { + color: #dc8164; +} + +html.theme-light .hljs-type, +html.theme-light .hljs-class .hljs-title, +html.theme-light .hljs-attribute { + color: #4c6c94; +} + +html.theme-light .hljs-symbol, +html.theme-light .hljs-bullet, +html.theme-light .hljs-link, +html.theme-light .hljs-meta, +html.theme-light .hljs-deletion, +html.theme-light .hljs-addition { + color: #8a5b81; +} + +html.theme-light .hljs-built_in, +html.theme-light .hljs-builtin-name, +html.theme-light .hljs-params { + color: #3d727d; +} + +html.theme-light .hljs-regexp, +html.theme-light .hljs-operator, +html.theme-light .hljs-selector-attr, +html.theme-light .hljs-selector-pseudo, +html.theme-light .hljs-selector-class, +html.theme-light .hljs-template-tag { + color: #8a5b81; +} + +html.theme-light .hljs-name, +html.theme-light .hljs-tag { + color: #4c6c94; +} + +html.theme-light .hljs-meta .hljs-string { + color: #556753; +} +/* ---------- Admonitions (Trilium-style, gefüllt) ---------- */ +.admonition { + --accent-color: var(--background-highlight); + --admonition-bg: var(--background-secondary); + border: 1px solid var(--accent-color); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15); + background: var(--admonition-bg); + border-radius: 0.5em; + padding: 1em; + padding-inline-start: 2.5em; + margin: 1.25em 0; + position: relative; + overflow: hidden; +} + +html.theme-dark .admonition.note { --admonition-bg: rgba(76, 108, 148, 0.16); } +html.theme-dark .admonition.tip { --admonition-bg: rgba(85, 103, 83, 0.16); } +html.theme-dark .admonition.important { --admonition-bg: rgba(138, 91, 129, 0.18); } +html.theme-dark .admonition.caution { --admonition-bg: rgba(177, 71, 82, 0.16); } +html.theme-dark .admonition.warning { --admonition-bg: rgba(220, 129, 100, 0.16); } +html.theme-dark .admonition { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); } + +html.theme-light .admonition.note { --admonition-bg: rgba(76, 108, 148, 0.18); } +html.theme-light .admonition.tip { --admonition-bg: rgba(85, 103, 83, 0.16); } +html.theme-light .admonition.important { --admonition-bg: rgba(138, 91, 129, 0.16); } +html.theme-light .admonition.caution { --admonition-bg: rgba(177, 71, 82, 0.16); } +html.theme-light .admonition.warning { --admonition-bg: rgba(220, 129, 100, 0.20); } + +.admonition p:last-child { + margin-bottom: 0; +} + +.admonition p, +.admonition h2 { + margin-top: 0; +} + +.admonition.note { --accent-color: #4c6c94; } +.admonition.tip { --accent-color: #556753; } +.admonition.important { --accent-color: #8a5b81; } +.admonition.caution { --accent-color: #b14752; } +.admonition.warning { --accent-color: #dc8164; } + +.admonition::before { + color: var(--accent-color); + font-family: boxicons !important; + position: absolute; + top: 1em; + inset-inline-start: 1em; +} + +.admonition.note::before { content: "\eb21"; } +.admonition.tip::before { content: "\ea0d"; } +.admonition.important::before { content: "\ea7c"; } +.admonition.caution::before { content: "\eac7"; } +.admonition.warning::before { content: "\eac5"; } +/* ---------- Tables (Harbor, theme-aware) ---------- */ +html.theme-dark { + --table-header-bg: rgba(231, 90, 80, 0.20); + --table-header-text: #efebdc; + --table-header-border: rgba(231, 90, 80, 0.45); + --table-stripe: rgba(255, 255, 255, 0.04); + --table-hover: rgba(231, 90, 80, 0.12); + --table-rowlabel-bg: rgba(255, 255, 255, 0.05); + --table-rowlabel-text: #efebdc; +} + +html.theme-light { + --table-header-bg: rgba(94, 129, 172, 0.16); + --table-header-text: #1c2d28; + --table-header-border: rgba(94, 129, 172, 0.40); + --table-stripe: rgba(0, 0, 0, 0.04); + --table-hover: rgba(94, 129, 172, 0.12); + --table-rowlabel-bg: rgba(0, 0, 0, 0.05); + --table-rowlabel-text: #1c2d28; +} + +.ck-content table, +#content table { + border-collapse: separate; + border-spacing: 0; + border: 1px solid var(--background-highlight); + border-radius: 8px; + overflow: hidden; + margin: 1em 0; +} + +.ck-content table th, +.ck-content table td, +#content table th, +#content table td { + border: none; + border-bottom: 1px solid var(--background-highlight); + border-right: 1px solid var(--background-highlight); + padding: 8px 12px; + text-align: left; + background-color: transparent !important; +} + +.ck-content table th:last-child, +.ck-content table td:last-child, +#content table th:last-child, +#content table td:last-child { + border-right: none; +} + +.ck-content table tr:last-child td, +#content table tr:last-child td { + border-bottom: none; +} + +.ck-content table thead th, +#content table thead th { + background-color: var(--table-header-bg) !important; + color: var(--table-header-text); + font-weight: 700; + border-bottom: 2px solid var(--table-header-border); +} + +.ck-content table tbody td:first-child, +#content table tbody td:first-child { + background-color: var(--table-rowlabel-bg) !important; + color: var(--table-rowlabel-text); + font-weight: 600; + white-space: nowrap; +} + +.ck-content table tbody tr:nth-child(even) td:not(:first-child), +#content table tbody tr:nth-child(even) td:not(:first-child) { + background-color: var(--table-stripe) !important; +} + +.ck-content table tbody tr:hover td, +#content table tbody tr:hover td { + background-color: rgba(94, 129, 172, 0.10) !important; +} + +.ck-content table .col-hover, +#content table .col-hover { + background-color: rgba(94, 129, 172, 0.10) !important; +} + +.ck-content table tbody tr:hover td.col-hover, +.ck-content table thead th.col-hover, +#content table tbody tr:hover td.col-hover, +#content table thead th.col-hover { + background-color: rgba(94, 129, 172, 0.18) !important; +} +/* ---------- Category subcategories ---------- */ +.blog-subcategories { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin: 0 0 1.25em; +} + +.blog-subcategory { + display: inline-flex; + align-items: center; + gap: 6px; + background: var(--background-secondary); + border: 1px solid var(--background-highlight); + border-radius: 8px; + padding: 4px 12px; + color: var(--text-heading); + text-decoration: none; + font-weight: 600; + transition: background-color 150ms ease, border-color 150ms ease; +} + +.blog-subcategory i { + color: var(--text-link); +} + +.blog-subcategory:hover { + background: var(--background-highlight); + border-color: var(--text-link); + color: var(--text-heading); + text-decoration: none; +} +/* ---------- Digital Garden note table ---------- */ +.blog-garden-table { + width: 100%; +} + +.blog-garden-table tbody td:first-child { + background: transparent !important; + font-weight: normal; +} + +.note-type { + display: inline-block; + font-size: 0.8em; + padding: 2px 10px; + border-radius: 8px; + background: var(--background-highlight); + color: var(--text-heading); + font-weight: 600; + text-transform: capitalize; + white-space: nowrap; +} +/* ---------- Digital Garden rows: clickable + sage hover ---------- */ +.blog-garden-table tbody tr { + cursor: pointer; +} + +#content .blog-garden-table tbody tr:hover td, +#content .blog-garden-table .col-hover { + background-color: rgba(169, 155, 122, 0.15) !important; +} + +#content .blog-garden-table tbody tr:hover td.col-hover { + background-color: rgba(169, 155, 122, 0.25) !important; +} +.note-state { + display: inline-flex; + align-items: center; + gap: 5px; + font-size: 0.8em; + padding: 2px 10px; + border-radius: 8px; + background: rgba(169, 155, 122, 0.20); + color: var(--text-heading); + font-weight: 600; + white-space: nowrap; +} + +.note-state i { + color: #a99b7a; +} + +.note-state.state-draft { + background: rgba(109, 109, 109, 0.22); +} + +.note-state.state-draft i { + color: #6d6d6d; +} + +.note-state.state-review { + background: rgba(119, 131, 138, 0.25); +} + +.note-state.state-review i { + color: #77838a; +} + +.note-state.state-unknown { + background: rgba(244, 67, 54, 0.18); +} + +.note-state.state-unknown i { + color: #F44336; +} + +/* ---------- Peppige Garden-Badges (dark) ---------- */ +html.theme-dark .note-state { + background: rgba(169, 155, 122, 0.40); + border: 1px solid #a99b7a; + color: #1b1b1b; +} +html.theme-dark .note-state i { + color: #1b1b1b; +} +html.theme-dark .note-state.state-draft { + background: rgba(244, 67, 54, 0.85); + border-color: #ff8a7f; + color: #1b1b1b; +} +html.theme-dark .note-state.state-draft i { + color: #1b1b1b; +} +html.theme-dark .note-state.state-review { + background: rgba(76, 108, 148, 0.85); + border-color: #8fb4e0; + color: #1b1b1b; +} +html.theme-dark .note-state.state-review i { + color: #1b1b1b; +} +html.theme-dark .note-state.state-unknown { + background: rgba(225, 206, 152, 0.85); + border-color: #f2e4b8; + color: #1b1b1b; +} +html.theme-dark .note-state.state-unknown i { + color: #1b1b1b; +} + +/* ---------- Peppige Garden-Badges (light) ---------- */ +html.theme-light .note-state { + background: rgba(85, 103, 83, 0.85); + border: 1px solid #556753; + color: #dfe4c4; +} +html.theme-light .note-state i { + color: #dfe4c4; +} +html.theme-light .note-state.state-draft { + background: rgba(220, 129, 100, 0.95); + border-color: #b85f3f; + color: #1c2d28; +} +html.theme-light .note-state.state-draft i { + color: #1c2d28; +} +html.theme-light .note-state.state-review { + background: rgba(94, 129, 172, 0.95); + border-color: #3d5f8a; + color: #dfe4c4; +} +html.theme-light .note-state.state-review i { + color: #dfe4c4; +} +html.theme-light .note-state.state-unknown { + background: rgba(177, 71, 82, 0.95); + border-color: #8f3a40; + color: #dfe4c4; +} +html.theme-light .note-state.state-unknown i { + color: #dfe4c4; +} +/* ---------- Code notes: always Harbordark like code boxes ---------- */ +#content.type-code pre { + background-color: #222222 !important; + color: #efebdc; + border: 1px solid #2e2e2e; + border-radius: 8px; + padding: 1em; + margin: 1em 0; +} + +#content.type-code code { + background-color: transparent !important; + color: #efebdc; + border: 0; +} + +html.theme-light #content.type-code pre { + background-color: #e8ecd0 !important; + color: #1c2d28; + border-color: #c3c9a6; +} + +html.theme-light #content.type-code code { + color: #1c2d28; +} +/* ---------- Code: line numbers + copy button ---------- */ +pre.code-processed { + position: relative; + display: flex; + align-items: flex-start; + line-height: 1.6; +} + +pre.code-processed .code-wrap { + flex: 1; + min-width: 0; + overflow-x: auto; + border-radius: 8px; +} + +pre.code-processed .code-wrap code { + display: block; + line-height: inherit; + padding: 0; + margin: 0; +} + +pre.code-processed .code-lines { + flex-shrink: 0; + user-select: none; + text-align: right; + padding: 0 12px 0 0; + margin: 0 12px 0 0; + border-right: 1px solid var(--background-highlight); + color: var(--text-menu); + white-space: pre; + font-family: "JetBrains Mono", Consolas, monospace; + font-size: 1em; + line-height: inherit; +} + +pre.code-processed .code-copy-btn, +.mermaid-source pre .code-copy-btn { + position: absolute; + top: 6px; + right: 6px; + z-index: 2; + font-size: 0.75em; + padding: 2px 10px; + border-radius: 6px; + border: 1px solid var(--background-highlight); + background: var(--background-secondary); + color: var(--text-heading); + cursor: pointer; + opacity: 0.6; + transition: opacity 150ms ease; +} + +pre.code-processed:hover .code-copy-btn, +.mermaid-source pre:hover .code-copy-btn { + opacity: 1; +} + +pre.code-processed .code-copy-btn:hover, +.mermaid-source pre .code-copy-btn:hover { + border-color: var(--text-link); + opacity: 1; +} +/* ---------- highlight.js line numbers ---------- */ +#content .hljs-ln { + border-collapse: collapse; + border: none !important; + box-shadow: none; + border-radius: 8px; + margin: 0; + width: auto; + line-height: 1.4; +} + +#content .hljs-ln td, +#content .hljs-ln th { + border: none !important; + background-color: transparent !important; + padding: 0; +} + +#content .hljs-ln tbody td:first-child, +#content .hljs-ln thead th:first-child { + background-color: transparent !important; +} + +#content .hljs-ln tbody tr:nth-child(even) td { + background-color: transparent !important; +} + +#content .hljs-ln .col-hover { + background-color: transparent !important; +} + +#content .hljs-ln tbody tr:hover td, +#content .hljs-ln tbody tr:hover td.col-hover { + background-color: rgba(94, 129, 172, 0.08) !important; +} + +html.theme-light #content .hljs-ln tbody tr:hover td, +html.theme-light #content .hljs-ln tbody tr:hover td.col-hover { + background-color: rgba(94, 129, 172, 0.08) !important; +} + +.hljs-ln-numbers { + user-select: none; + text-align: right; + padding-right: 12px !important; + padding-left: 4px; + border-right: 1px solid var(--background-highlight) !important; + color: var(--text-menu); + white-space: nowrap; + vertical-align: top; + font-family: "JetBrains Mono", Consolas, monospace; +} + +.hljs-ln-code { + padding-left: 12px !important; + white-space: pre; + vertical-align: top; +} +/* ---------- Scrollbars (Harbor) ---------- */ +::-webkit-scrollbar { + width: 12px; + height: 12px; +} + +::-webkit-scrollbar-track { + background: var(--scrollbar-track); +} + +::-webkit-scrollbar-thumb { + background: var(--scrollbar-thumb); + border-radius: 6px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--scrollbar-hover); +} + +* { + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); +} + +/* ---------- Code boxes: scrollbars ---------- */ +pre, +pre.code-processed .code-wrap, +.hljs-ln-code { + scrollbar-color: #2e2e2e #1b1b1b; +} + +pre::-webkit-scrollbar-thumb, +pre.code-processed .code-wrap::-webkit-scrollbar-thumb, +.hljs-ln-code::-webkit-scrollbar-thumb { + background: #2e2e2e; +} + +pre::-webkit-scrollbar-thumb:hover, +pre.code-processed .code-wrap::-webkit-scrollbar-thumb:hover, +.hljs-ln-code::-webkit-scrollbar-thumb:hover { + background: #3f3f3f; +} + +pre::-webkit-scrollbar-track, +pre.code-processed .code-wrap::-webkit-scrollbar-track, +.hljs-ln-code::-webkit-scrollbar-track { + background: #1b1b1b; +} + +html.theme-light pre, +html.theme-light pre.code-processed .code-wrap, +html.theme-light .hljs-ln-code { + scrollbar-color: #b3ba96 #d0d6b4; +} + +html.theme-light pre::-webkit-scrollbar-thumb, +html.theme-light pre.code-processed .code-wrap::-webkit-scrollbar-thumb, +html.theme-light .hljs-ln-code::-webkit-scrollbar-thumb { + background: #b3ba96; +} + +html.theme-light pre::-webkit-scrollbar-thumb:hover, +html.theme-light pre.code-processed .code-wrap::-webkit-scrollbar-thumb:hover, +html.theme-light .hljs-ln-code::-webkit-scrollbar-thumb:hover { + background: #c3c9a6; +} + +html.theme-light pre::-webkit-scrollbar-track, +html.theme-light pre.code-processed .code-wrap::-webkit-scrollbar-track, +html.theme-light .hljs-ln-code::-webkit-scrollbar-track { + background: #d0d6b4; +} + +/* ---------- Link icons / markers: internal links without arrow, external links keep a marker ---------- */ +#content a::after, +#content a::before, +#content-footer .navigation a::after, +#content-footer .navigation a::before, +a.next::after, +a.previous::before, +.bmc-btn::after, +.bmc-btn::before, +.bmc-powered::after, +.bmc-powered::before { + content: none !important; +} + +#content a[href^="http://"]:not([href^="https://YOUR-INSTANCE.example.com"])::after, +#content a[href^="https://"]:not([href^="https://YOUR-INSTANCE.example.com"])::after { + content: " ↗" !important; + display: inline-block; + margin-left: 3px; + font-size: 0.85em; + color: var(--text-link); +} + +/* inline text links (in paragraphs/lists): colour only */ +#content p a:not([class]), +#content li a:not([class]) { + color: var(--text-link); + text-decoration: none; + background: transparent; + border: 0; + padding: 0; + border-radius: 0; +} + +#content p a:not([class]):hover, +#content li a:not([class]):hover { + color: var(--text-heading); + background: transparent; +} + +/* action links as buttons (subtle tint, noticeable on hover) */ +.blog-pn { + padding: 6px 14px; + border: 1px solid rgba(231, 90, 80, 0.30); + border-radius: 8px; + background: rgba(231, 90, 80, 0.08); + transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease; +} + +html.theme-light .blog-pn { + border-color: rgba(76, 108, 148, 0.30); + background: rgba(76, 108, 148, 0.08); +} + +.blog-pn:hover { + background: rgba(231, 90, 80, 0.18); + border-color: #e75a50; +} + +html.theme-light .blog-pn:hover { + background: rgba(76, 108, 148, 0.15); + border-color: #4c6c94; +} + +/* ---------- Mermaid diagrams - Harbor, theme-following ---------- */ +/* + * The blog renders inline Mermaid diagrams with the default theme, so the + * generated SVG carries light-blue node fills that clash with Harbor. + * Override the SVG element colours here; the selectors hang off + * html.theme-dark / html.theme-light, so the diagrams follow the theme + * toggle automatically without re-rendering. + */ + +.mermaid { + margin: 1.25em auto; + overflow-x: auto; + background: transparent; +} + +.mermaid svg { + max-width: 100%; + height: auto; +} + +/* Text in node labels and titles */ +html.theme-dark .mermaid svg text, +html.theme-dark .mermaid svg tspan, +html.theme-dark .mermaid svg .nodeLabel, +html.theme-dark .mermaid svg .edgeLabel p { + fill: #efebdc !important; + color: #efebdc !important; +} + +html.theme-light .mermaid svg text, +html.theme-light .mermaid svg tspan, +html.theme-light .mermaid svg .nodeLabel, +html.theme-light .mermaid svg .edgeLabel p { + fill: #1c2d28 !important; + color: #1c2d28 !important; +} + +/* Graph/node title */ +html.theme-dark .mermaid svg .titleText text, +html.theme-dark .mermaid svg .node .label .nodeLabel { + fill: #efebdc !important; + color: #efebdc !important; +} + +html.theme-light .mermaid svg .titleText text, +html.theme-light .mermaid svg .node .label .nodeLabel { + fill: #1c2d28 !important; + color: #1c2d28 !important; +} + +/* Node shapes (rectangles, rounded boxes, ellipses, diamonds) */ +html.theme-dark .mermaid svg .node rect, +html.theme-dark .mermaid svg .node polygon, +html.theme-dark .mermaid svg .node circle, +html.theme-dark .mermaid svg .node ellipse, +html.theme-dark .mermaid svg .node path, +html.theme-dark .mermaid svg .cluster rect { + fill: #232323 !important; + stroke: #77838a !important; +} + +html.theme-light .mermaid svg .node rect, +html.theme-light .mermaid svg .node polygon, +html.theme-light .mermaid svg .node circle, +html.theme-light .mermaid svg .node ellipse, +html.theme-light .mermaid svg .node path, +html.theme-light .mermaid svg .cluster rect { + fill: #d0d6b4 !important; + stroke: #4c6c94 !important; +} + +/* Rounded corners on rectangular node boxes and subgraph clusters (8 px, like the blog cards) */ +html.theme-dark .mermaid svg .node rect, +html.theme-light .mermaid svg .node rect, +html.theme-dark .mermaid svg .cluster rect, +html.theme-light .mermaid svg .cluster rect { + rx: 8px !important; + ry: 8px !important; +} + +/* Edge lines: stroke only (a filled edge path would look like a polygon) */ +html.theme-dark .mermaid svg .edgePaths path { + fill: none !important; + stroke: #a99b7a !important; +} + +html.theme-light .mermaid svg .edgePaths path { + fill: none !important; + stroke: #7d8794 !important; +} + +/* Arrowheads (markers): filled triangles */ +html.theme-dark .mermaid svg marker.flowchart-v2, +html.theme-dark .mermaid svg .arrowMarkerPath { + fill: #a99b7a !important; + stroke: #a99b7a !important; +} + +html.theme-light .mermaid svg marker.flowchart-v2, +html.theme-light .mermaid svg .arrowMarkerPath { + fill: #7d8794 !important; + stroke: #7d8794 !important; +} + +/* Edge labels: HTML text inside a foreignObject (div.labelBkg > span.edgeLabel); + the label panel background lives on the g.edgeLabel element itself */ +html.theme-dark .mermaid svg g.edgeLabel { + background: #1b1b1b !important; + fill: #efebdc !important; + color: #efebdc !important; +} + +html.theme-dark .mermaid svg .edgeLabel .labelBkg { + fill: #1b1b1b !important; + background: #1b1b1b !important; + color: #efebdc !important; +} + +html.theme-dark .mermaid svg .edgeLabel .labelBkg .edgeLabel { + fill: #efebdc !important; + color: #efebdc !important; + background: #1b1b1b !important; +} + +html.theme-dark .mermaid svg .edgeLabel .labelBkg .edgeLabel p { + fill: #efebdc !important; + color: #efebdc !important; + background: #1b1b1b !important; +} + +html.theme-light .mermaid svg g.edgeLabel { + background: #d0d6b4 !important; + fill: #1c2d28 !important; + color: #1c2d28 !important; +} + +html.theme-light .mermaid svg .edgeLabel .labelBkg { + fill: #d0d6b4 !important; + background: #d0d6b4 !important; + color: #1c2d28 !important; +} + +html.theme-light .mermaid svg .edgeLabel .labelBkg .edgeLabel { + fill: #1c2d28 !important; + color: #1c2d28 !important; + background: #d0d6b4 !important; +} + +html.theme-light .mermaid svg .edgeLabel .labelBkg .edgeLabel p { + fill: #1c2d28 !important; + color: #1c2d28 !important; + background: #d0d6b4 !important; +} + +/* Subgraph cluster border + label */ +html.theme-dark .mermaid svg .cluster rect { + stroke: #2e2e2e !important; + fill: rgba(27, 27, 27, 0.35) !important; +} + +html.theme-light .mermaid svg .cluster rect { + stroke: #c3c9a6 !important; + fill: rgba(208, 214, 180, 0.40) !important; +} + +html.theme-dark .mermaid svg .cluster .nodeLabel, +html.theme-dark .mermaid svg .cluster-label text { + fill: #a99b7a !important; + color: #a99b7a !important; +} + +html.theme-light .mermaid svg .cluster .nodeLabel, +html.theme-light .mermaid svg .cluster-label text { + fill: #556753 !important; + color: #556753 !important; +} +/* ---------- G-code / Zusatz-Scopes (name = G/M-Codes, attr = Parameter) ---------- */ +.hljs-name { color: #E1CE98; } +.hljs-attr { color: #77838a; } +html.theme-light .hljs-name { color: #4c6c94; } +html.theme-light .hljs-attr { color: #556753; } \ No newline at end of file