/* vaelum.dev — structure shared by every theme.
 *
 * This file owns layout and components; it never picks a colour or a face.
 * Each page loads one theme from themes/<name>.css that sets the tokens below
 * (and may restyle components in its own voice): `home` for the start page,
 * and one per project, so a project's pages look like the project.
 *
 * Fonts are self-hosted (OFL, licences beside the files). A face is only
 * downloaded when a theme uses it.
 */

@font-face {
  font-family: "Geist";
  src: url("fonts/geist-latin-wght-normal.woff2") format("woff2-variations");
  font-weight: 100 900; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist";
  src: url("fonts/geist-latin-ext-wght-normal.woff2") format("woff2-variations");
  font-weight: 100 900; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Geist Mono";
  src: url("fonts/geist-mono-latin-wght-normal.woff2") format("woff2-variations");
  font-weight: 100 900; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist Mono";
  src: url("fonts/geist-mono-latin-ext-wght-normal.woff2") format("woff2-variations");
  font-weight: 100 900; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("fonts/jetbrains-mono-latin-wght-normal.woff2") format("woff2-variations");
  font-weight: 100 800; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("fonts/jetbrains-mono-latin-ext-wght-normal.woff2") format("woff2-variations");
  font-weight: 100 800; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("fonts/jetbrains-mono-latin-wght-italic.woff2") format("woff2-variations");
  font-weight: 100 800; font-style: italic; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Neutral fallbacks; every theme overrides them. */
  --bg: #ffffff;
  --surface: #ffffff;
  --surface-2: #f3f4f6;
  --fg: #111318;
  --muted: #5d6470;
  --border: #e3e6ea;
  --accent: #2f5bd3;
  --accent-fg: #ffffff;
  --accent-soft: #eef2fc;
  --link: var(--accent);
  --code-bg: var(--surface-2);
  --code-fg: var(--fg);
  --pre-bg: var(--surface);
  --selection: color-mix(in oklab, var(--accent) 22%, transparent);

  --note: var(--accent);
  --tip: #2f8f4e;
  --warn: #b7791f;
  --danger: #c93b32;

  --hl-keyword: #7a3e9d;
  --hl-string: #2f6f3e;
  --hl-number: #a4461b;
  --hl-comment: #6f7c8c;
  --hl-type: #1f5f8f;
  --hl-call: #2b3f88;

  --font-body: system-ui, sans-serif;
  --font-head: var(--font-body);
  --font-ui: var(--font-body);
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --body-size: 1rem;
  --body-lh: 1.7;
  --head-weight: 700;
  --head-track: -0.015em;
  --h1-size: 2.25rem;
  --h2-size: 1.5rem;
  --h3-size: 1.2rem;

  --radius: 8px;
  --radius-lg: 10px;
  --measure: 44rem;
  --gutter: clamp(1rem, 3vw, 2rem);
  --bar-height: 3.5rem;
  /* What the footer covers at the bottom of the screen: nothing where it is
     a bar after the page; on the home look, where it floats as pills, their
     height, their distance from the edge and a little air. A page keeps its
     last lines out of it (main's own bottom padding is more than this). */
  --footer-room: 0px;
}
body[data-look="home"] { --footer-room: 3.5rem; }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* A column, so the content fills a short page. */
  display: flex;
  flex-direction: column;
  min-height: 100svh;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--body-size);
  line-height: var(--body-lh);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--selection); }
a { color: var(--link); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.skip {
  position: absolute; left: 1rem; top: -4rem; z-index: 20;
  background: var(--surface); color: var(--fg); padding: 0.5rem 0.75rem;
  font-family: var(--font-ui); border: 1px solid var(--border); border-radius: var(--radius);
}
.skip:focus { top: 1rem; }

/* ------------------------------------------------------------ project bar */

.project-bar {
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  font-family: var(--font-ui);
  font-size: 0.875rem;
}
body[data-look="home"] .project-bar { display: none; }

.project-bar-inner {
  max-width: 88rem;
  margin: 0 auto;
  min-height: var(--bar-height);
  padding: 0.5rem var(--gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.25rem;
}
.project-bar-links { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1.25rem; margin-right: auto; }

.bar-home { color: var(--muted); text-decoration: none; }
.bar-home::before { content: "\2190\00a0"; }
.bar-home:hover { color: var(--fg); }

.bar-brand { display: inline-flex; align-items: center; gap: 0.55rem; color: var(--fg); text-decoration: none; }
.bar-mark { display: inline-block; width: 1.4rem; height: 1.4rem; flex: none; }
.bar-name { font-weight: 650; font-size: 1rem; }

.bar-links ul { display: flex; gap: 0.25rem 1rem; margin: 0; padding: 0; list-style: none; }
.bar-links a { color: var(--muted); text-decoration: none; padding: 0.3rem 0; }
.bar-links a:hover { color: var(--fg); }
.bar-links a[aria-current] { color: var(--fg); box-shadow: inset 0 -2px 0 var(--accent); }

.search { position: relative; flex: 0 1 15rem; }
.search[hidden] { display: none; }
.search input {
  width: 100%; font: inherit; color: var(--fg);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 0.4rem 0.65rem;
}
.search-results {
  position: absolute; right: 0; top: calc(100% + 0.35rem); z-index: 10;
  width: min(28rem, calc(100vw - 2rem)); max-height: 70vh; overflow: auto;
  margin: 0; padding: 0.35rem; list-style: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: 0 16px 40px -16px rgb(0 0 0 / 0.35);
}
.search-results a { display: block; padding: 0.5rem 0.6rem; border-radius: calc(var(--radius) - 2px); text-decoration: none; color: var(--fg); }
.search-results a:hover, .search-results a:focus-visible { background: var(--surface-2); }
.search-title { display: block; font-weight: 600; }
.search-snippet { display: block; color: var(--muted); font-size: 0.82rem; line-height: 1.4; }
.search-empty { padding: 0.5rem 0.6rem; color: var(--muted); }

/* ----------------------------------------------------------------- layout */

.layout { flex: 1 0 auto; width: 100%; max-width: 88rem; margin: 0 auto; padding: 0 var(--gutter); }
body[data-look="home"] .layout { max-width: none; padding: 0; }
main { min-width: 0; padding: 2.5rem 0 4.5rem; outline: none; }
body[data-look="home"] main { padding: 0; }

.sidebar, .toc-col { font-family: var(--font-ui); font-size: 0.875rem; }
body:not([data-kind="docs"]) .sidebar,
body:not([data-kind="docs"]) .toc-col { display: none; }

.sidebar { border-bottom: 1px solid var(--border); padding: 0.75rem 0; }
.sidebar > summary { cursor: pointer; color: var(--muted); }

@media (min-width: 60rem) {
  body[data-kind="docs"] .layout { display: grid; grid-template-columns: 15.5rem minmax(0, 1fr); gap: 3rem; }
  .sidebar { border: 0; padding: 2.5rem 0; }
  .sidebar > summary { display: none; }
  .sidebar > div { position: sticky; top: 1.5rem; max-height: calc(100vh - 3rem - var(--footer-room)); overflow: auto; padding-right: 0.25rem; }
}
@media (min-width: 78rem) {
  body[data-kind="docs"] .layout { grid-template-columns: 15.5rem minmax(0, 1fr) 13rem; }
  .toc-col { padding: 2.5rem 0; }
  .toc-col > .toc { position: sticky; top: 1.5rem; }
}
@media (max-width: 77.99rem) { .toc-col { display: none; } }

.docs-nav ul { list-style: none; margin: 0; padding: 0; }
.docs-nav-title { margin: 0 0 0.75rem; font-weight: 650; }
.docs-nav-title a { color: var(--fg); text-decoration: none; }
.docs-nav-title span { color: var(--muted); font-weight: 400; }
.docs-nav li a {
  display: block; padding: 0.32rem 0.65rem; border-radius: calc(var(--radius) - 2px);
  color: var(--muted); text-decoration: none; line-height: 1.35;
}
.docs-nav li.nested a { padding-left: 1.3rem; }
.docs-nav li a:hover { color: var(--fg); background: var(--surface-2); }
.docs-nav li a[aria-current="page"] { color: var(--fg); background: var(--surface-2); font-weight: 600; }
.docs-nav-section { margin: 1rem 0 0.3rem; padding-left: 0.65rem; color: var(--fg); font-weight: 600; }

.toc-title { margin: 0 0 0.5rem; font-weight: 600; }
.toc ul { list-style: none; margin: 0; padding: 0; }
.toc a { display: block; padding: 0.2rem 0; color: var(--muted); text-decoration: none; line-height: 1.35; }
.toc a:hover { color: var(--fg); }
.toc .toc-l3 a { padding-left: 0.85rem; font-size: 0.82rem; }

.navigating main { opacity: 0.55; transition: opacity 120ms 80ms; }

/* ----------------------------------------------------------------- footer */

/* The legal links are required on every page: always visible text, never
   collapsed on small screens. On a project's pages they sit in a bar after
   the page, the copyright on the left and the legal links on the right. */
.site-footer {
  border-top: 1px solid var(--border);
  background: var(--bg);
  font-family: var(--font-ui);
  font-size: 0.875rem;
}
.site-footer-inner {
  max-width: 88rem;
  margin: 0 auto;
  min-height: var(--bar-height);
  padding: 0.5rem var(--gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem 1.25rem;
}
.footer-copy { margin: 0; color: var(--muted); }
.site-footer a { display: inline-block; padding: 0.35rem 0; color: var(--muted); text-decoration: none; }
.site-footer a:hover { color: var(--fg); text-decoration: underline; }
/* Bottom right, also when a narrow screen wraps it below the copyright. */
.footer-legal { margin-left: auto; }
.footer-legal ul { display: flex; flex-wrap: wrap; gap: 0 1.25rem; margin: 0; padding: 0; list-style: none; }
.site-footer .footer-back { display: none; }

/* On the home look (the overview, the Impressum and the privacy notice) they
   float over the page as pills at the bottom of the screen instead, with no
   bar of their own, so a page runs to the screen's edge and they stay on
   screen however far it scrolls. On the Impressum and the privacy notice a
   highlighted pill in the middle leads back to the start. */
body[data-look="home"] .site-footer {
  position: fixed; left: 0; right: 0; bottom: 0.75rem; z-index: 5;
  border: 0; background: none;
  pointer-events: none;   /* only the pills take clicks, not the gap between them */
  font-size: 0.8125rem;
}
body[data-look="home"] .site-footer-inner {
  min-height: 0;
  padding: 0 var(--gutter);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 0.5rem;
  white-space: nowrap;
}
body[data-look="home"] .footer-copy { grid-column: 1; justify-self: start; }
body[data-look="home"] .footer-back { grid-column: 2; }
body[data-look="home"] .footer-legal { grid-column: 3; justify-self: end; margin-left: 0; }
body[data-look="home"] :is(.footer-copy, .site-footer a) {
  pointer-events: auto;
  display: inline-flex; align-items: center;
  height: 2.25rem; margin: 0; padding: 0 0.9rem;
  border: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  color: var(--muted); text-decoration: none;
  transition: color 160ms, border-color 160ms, background-color 160ms;
}
body[data-look="home"] .site-footer a:is(:hover, :focus-visible) {
  color: var(--fg); border-color: var(--muted); text-decoration: none;
  background: color-mix(in srgb, var(--bg) 90%, transparent);
}
/* The copyright is a note, not a control: no border. */
body[data-look="home"] .site-footer .footer-copy { border-color: transparent; }

body[data-look="home"] .site-footer .footer-back { display: none; gap: 0.45rem; font-weight: 600; }
body[data-look="home"]:is([data-src="impressum.md"], [data-src="privacy.md"]) .site-footer .footer-back { display: inline-flex; }
body[data-look="home"] .site-footer .footer-back,
body[data-look="home"] .site-footer .footer-back:is(:hover, :focus-visible) { background: var(--fg); border-color: var(--fg); color: var(--bg); }
body[data-look="home"] .site-footer .footer-back:hover { filter: brightness(1.15); }
.footer-back::before { content: "\2190"; transition: transform 160ms; }
.footer-back:hover::before { transform: translateX(-2px); }
/* Too narrow for three: the way back takes a row of its own above the rest. */
@media (max-width: 40rem) {
  body[data-look="home"] .footer-back { grid-row: 1; grid-column: 1 / -1; justify-self: center; }
}
body[data-look="home"] .footer-legal ul { flex-wrap: nowrap; gap: 0.5rem; }
@media (max-width: 24rem) {
  body[data-look="home"] .site-footer { font-size: 0.75rem; }
  body[data-look="home"] .site-footer-inner { padding: 0 0.5rem; }
  body[data-look="home"] :is(.footer-copy, .site-footer a) { padding: 0 0.55rem; }
  body[data-look="home"] .site-footer .footer-copy { padding: 0 0.25rem; }   /* no border to keep the text off */
  body[data-look="home"] :is(.site-footer-inner, .footer-legal ul) { gap: 0.35rem; }
}

/* ------------------------------------------------------------------ prose */

.prose { max-width: var(--measure); }
body[data-kind="site"]:not([data-look="home"]) .prose { margin: 0 auto; }
body[data-look="home"] .prose { max-width: none; }
.prose > :first-child { margin-top: 0; }

.prose h1, .prose h2, .prose h3, .prose h4 {
  font-family: var(--font-head);
  font-weight: var(--head-weight);
  letter-spacing: var(--head-track);
  line-height: 1.2;
  scroll-margin-top: 1.5rem;
  text-wrap: balance;
}
.prose h1 { font-size: var(--h1-size); margin: 0 0 1.25rem; }
.prose h2 { font-size: var(--h2-size); margin: 2.75rem 0 0.75rem; }
.prose h3 { font-size: var(--h3-size); margin: 2rem 0 0.5rem; }
.prose h4 { font-size: 1rem; margin: 1.5rem 0 0.5rem; }

.prose .anchor {
  margin-left: 0.4rem; color: var(--muted); text-decoration: none; font-weight: 400;
  opacity: 0; transition: opacity 120ms;
}
.prose :is(h1, h2, h3, h4):hover .anchor, .prose .anchor:focus-visible { opacity: 1; }

.prose p, .prose ul, .prose ol, .prose blockquote, .prose pre, .prose .table-wrap, .prose details { margin: 0 0 1.1rem; }
.prose ul, .prose ol { padding-left: 1.4rem; }
.prose li { margin: 0.2rem 0; }
.prose li > p { margin: 0.4rem 0; }
.prose li.task { list-style: none; margin-left: -1.3rem; }
.prose hr { border: 0; border-top: 1px solid var(--border); margin: 2.5rem 0; }
.prose img, .prose video { max-width: 100%; height: auto; }
.prose .pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: start; }
@media (max-width: 640px) { .prose .pair { grid-template-columns: 1fr; } }

.prose blockquote { margin-left: 0; padding: 0.1rem 0 0.1rem 1rem; border-left: 3px solid var(--border); color: var(--muted); }

.callout { margin: 0 0 1.1rem; padding: 0.8rem 1rem; border-left: 3px solid var(--note); background: var(--surface-2); border-radius: 0 var(--radius) var(--radius) 0; }
.callout > :last-child { margin-bottom: 0; }
.callout-title { margin: 0 0 0.25rem; font-family: var(--font-ui); font-weight: 650; font-size: 0.875rem; }
.callout-tip { border-left-color: var(--tip); }
.callout-warning { border-left-color: var(--warn); }
.callout-caution { border-left-color: var(--danger); }

.prose code {
  font-family: var(--font-mono); font-size: 0.86em;
  background: var(--code-bg); color: var(--code-fg);
  padding: 0.12em 0.35em; border-radius: calc(var(--radius) - 3px);
}
.prose pre {
  position: relative;
  font-size: 0.86rem; line-height: 1.6;
  background: var(--pre-bg); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 0.9rem 1rem; overflow-x: auto;
  max-width: min(100%, 54rem); width: max-content; min-width: 100%;
}
.prose pre code { background: none; color: inherit; padding: 0; font-size: inherit; border-radius: 0; }

.hl-keyword { color: var(--hl-keyword); }
.hl-string { color: var(--hl-string); }
.hl-number { color: var(--hl-number); }
.hl-comment { color: var(--hl-comment); font-style: italic; }
.hl-type { color: var(--hl-type); }
.hl-call { color: var(--hl-call); }
.hl-key { color: var(--hl-type); }
.hl-tag { color: var(--hl-keyword); }
.hl-prompt { color: var(--muted); user-select: none; }
.hl-output { color: var(--muted); }
.hl-added { color: var(--hl-string); }
.hl-removed { color: var(--hl-number); }
.hl-meta { color: var(--hl-type); }

.table-wrap { overflow-x: auto; }
.prose table { border-collapse: collapse; font-family: var(--font-ui); font-size: 0.9rem; }
.prose th, .prose td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
.prose th { font-weight: 650; }

/* --------------------------------------------------------------- versions */

.versions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; font-family: var(--font-ui); font-size: 0.875rem; }
.versions:not(:empty) { margin-bottom: 1.75rem; max-width: var(--measure); }
.version-banner { flex: 1 1 20rem; padding: 0.6rem 0.85rem; background: var(--surface-2); border-left: 3px solid var(--warn); border-radius: 0 var(--radius) var(--radius) 0; }
.version-switch { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--muted); margin-left: auto; }
.version-switch select { font: inherit; color: var(--fg); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 0.25rem 0.45rem; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0s !important; animation: none !important; }
}
