/* components/melucio-a11y.css */
/* melucio-a11y.css — Seiten-Wirkungen des <melucio-a11y>-Menues.
 *
 * Im <head> der Seite einbinden (das Bedien-Panel selbst kommt aus
 * melucio-a11y.js / Shadow DOM). Diese Datei liefert die universellen Teile:
 *   1. die @font-face der beiden Lese-Schriften (self-hosted, DSGVO-konform),
 *   2. die :root[data-font] / :root[data-spacing] Variablen-Zuordnung.
 *
 * INTEGRATIONS-VERTRAG (das Projekt muss diese Variablen anwenden):
 *   html { font-family: var(--body-font, <eigener System-Stack>); }
 *   body { line-height: var(--read-lh, <eigener Default>);
 *          letter-spacing: var(--read-ls, normal); }
 *   html { font-size: calc(<Basis>px * var(--font-scale, 1)); }
 * Die High-Contrast-Palette (:root[data-contrast='high'] { --fg: ...; ... })
 * bleibt bewusst beim Projekt — jede Marke hat ihre eigene Palette.
 *
 * SCHRIFT-DATEIEN: die sechs woff2 unter /fonts/ selbst hosten. Quelle:
 *   npm i @fontsource/atkinson-hyperlegible @fontsource/opendyslexic
 *   und die woff2 nach public/fonts/ kopieren.
 */

/* Kein blaues Aufblitzen beim Antippen (Android-Tap-Hervorhebung).
   Steht bewusst AUCH hier, nicht nur in melucio-reset.css: manche Seiten
   (etwa reine Rechtsseiten wie Impressum oder Datenschutz, einzelne
   Demoseiten) laden weder Reset noch Site-CSS — diese Datei ist dort das
   einzige geteilte Stylesheet. Doppelt mit dem Reset ist die Regel folgenlos (gleicher Wert).
   Der sichtbare Fokusring kommt aus :focus-visible und bleibt unberuehrt. */
* {
  -webkit-tap-highlight-color: transparent;
}


@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/atkinson-hyperlegible-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/atkinson-hyperlegible-latin-400-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/atkinson-hyperlegible-latin-700-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'OpenDyslexic';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/opendyslexic-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'OpenDyslexic';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/opendyslexic-latin-400-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'OpenDyslexic';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/opendyslexic-latin-700-normal.woff2') format('woff2');
}

/* Lese-Schriftart umschaltbar. Default = unset (System-Stack des Projekts). */
:root[data-font='hyper'] {
  --body-font: 'Atkinson Hyperlegible', system-ui, sans-serif;
}
:root[data-font='dyslexic'] {
  --body-font: 'OpenDyslexic', system-ui, sans-serif;
}

/* Textabstand umschaltbar (Zeilenhoehe + Buchstabenabstand). */
:root[data-spacing='loose'] {
  --read-lh: 1.95;
  --read-ls: 0.02em;
}
:root[data-spacing='xloose'] {
  --read-lh: 2.2;
  --read-ls: 0.045em;
}

/* Bewegung aus (Schalter im Menue, data-motion="reduce" auf <html>).
   Greift auf jeder Seite, die diese Datei laedt, auch ohne eigene Regel.

   Bewusst Dauer 0.01ms statt "animation: none": Viele Seiten blenden
   Inhalte per Animation mit fill-mode forwards EIN (Startzustand
   unsichtbar). "none" liesse sie im Startzustand stehen, also unsichtbar;
   eine fast leere Dauer springt sofort in den Endzustand, und
   animationend/transitionend feuern weiterhin (Skripte, die darauf
   warten, bleiben nicht haengen). Wer die Animationen auf einer Seite ganz
   entfernen will, schreibt dort "animation: none" samt Endzustand.

   Die Systemeinstellung (prefers-reduced-motion) deckt diese Datei NICHT
   ab; das bleibt Sache der Seite (bei den Apps mit melucio-breakpoints.css
   steht dieselbe Regel dort unter der Media Query). */
html[data-motion='reduce'] {
  scroll-behavior: auto !important;
}
html[data-motion='reduce'] *,
html[data-motion='reduce'] *::before,
html[data-motion='reduce'] *::after {
  animation-duration: 0.01ms !important;
  animation-delay: 0s !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.01ms !important;
  transition-delay: 0s !important;
  scroll-behavior: auto !important;
}

/* components/melucio-tokens.css */
/* ============================================================================
   meluciolabs.de — Farbtoken fuer hell und dunkel, an EINER Stelle, dazu das
   Wenige, was jede der einundzwanzig Seiten davon ableitet: die Kopfzeile in
   drei Spalten und die Knoepfe darin. Das MENUE steht dagegen in
   melucio-nav.css, denn die Videoraum-Seiten haben keins und laden sie nicht.

   ANLASS (22.09.2026): Das Portfolio war die einzige eigene Seite ohne hellen
   Modus. Der Umschalter (components/melucio-theme-toggle.js) lag fertig im
   Ordner und war auf keiner der zwanzig Seiten eingebunden; melucio-site.css
   kannte nur eine dunkle Palette, und die Rechtsseiten trugen ihre Farben
   jede noch einmal in einem eigenen <style>.

   AUFBAU (CLAUDE.md, Punkt 20):
     1. Hell steht auf blankem :root.
     2. Dunkel steht ZWEIMAL — unter @media (prefers-color-scheme: dark),
        abgesichert mit :root:not([data-theme="light"]), und noch einmal
        unter :root[data-theme="dark"]. Nur so gewinnt der Umschalter in
        beide Richtungen.
   Keine Farbe hat ihre EINZIGE Definition in einem Media-Block; was im
   Media-Block steht, steht oben auf :root auch.

   Die beiden dunklen Bloecke sind wortgleich und muessen es bleiben.
   Nachgezaehlt wird das, nicht geglaubt:
       node apps/meluciolabs/_tools/pruefe-themebloecke.mjs
   (laeuft im PR-Check ueber tests-vor-merge.yml mit).

   LADEREIHENFOLGE: nach melucio-reset.css, vor melucio-site.css und vor dem
   <style> der Seite. Der Reset setzt --bg/--fg/--muted selbst, und sein
   html[data-theme="dark"] traegt dieselbe Spezifitaet wie :root[data-theme]
   hier — wer diese Datei davor laedt, bekommt im Dunkeln den Reset-Grauwert.
   ========================================================================= */

:root {
    color-scheme: light;

    /* ---- Flaechen ---- */
    --bg: #f6f6fb;
    --bg-card: #ffffff;
    /* Alias fuer die Rechtsseiten, die ihre Karte --surface nennen. */
    --surface: #ffffff;
    /* Zweite deckende Flaeche (Eingabeleiste in /ki-demo). */
    --surface-2: #eef0f7;

    /* ---- Schrift ---- */
    --text: #15151f;
    /* Gemessen auf --bg: 6,4:1. #888 (der dunkle Wert) kaeme hier auf 3,5:1
       und faellt fuer Fliesstext durch. */
    --text-muted: #55556a;
    /* Alias fuer die Rechtsseiten. */
    --muted: #55556a;
    /* Schrift auf einer gefuellten AKZENT-Flaeche (--accent). Kippt im hohen
       Kontrast mit, weil der Akzent dort seine Helligkeit wechselt. */
    --on-accent: #ffffff;
    /* Schrift und Symbole auf den MARKEN-VERLAEUFEN. Die Verlaeufe sind in
       beiden Fassungen dieselben Farben, also ist es auch diese Schrift —
       und sie darf im hohen Kontrast NICHT mitkippen. Genau das war am
       22.09.2026 abends der Fall: --on-accent wurde dort dunkel, und die
       Knopfschrift landete mit 2,93:1 auf dem dunklen Ende von --gradient-1,
       schlechter als die 3,66:1 vorher. */
    --on-gradient: #ffffff;
    /* Vier der fuenf Marken-Verlaeufe sind HELL, und weisse Symbole darauf
       sind kaum zu sehen. Gemessen 22.09.2026: weiss auf #43e97b 1,59:1,
       auf #38f9d7 1,34:1, auf #4facfe 2,41:1, auf #f093fb 2,03:1 — ein
       Symbol braucht 3:1 (WCAG 1.4.11). Dieselben Flaechen mit dunklem
       Symbol: 7,5 bis 13,3:1. Die Verlaeufe bleiben, das Zeichen darin
       wechselt. */
    --on-gradient-hell: #15151f;

    /* ---- Akzent ----
       Seit 25.09.2026 aus der Logo-Familie ([[marke-lila-nicht-gruen]]):
       #7C6AF5, hell #A99EF8, dunkel #6355D0. Vorher stand hier Indigo
       (#4f46e5), das neben dem Logo wie eine zweite Marke aussah. */
    --accent: #6355D0;
    /* Im Hellen ist der Hover-Ton DUNKLER, nicht heller: der helle Logo-Ton
       #A99EF8 traegt auf Weiss nicht. */
    --accent-hover: #4A36A8;
    /* Der Akzent als SCHRIFT, getrennt von --accent (CLAUDE.md, Punkt 20).
       Im Dunkeln misst #7C6AF5 auf dem Grund zu wenig fuer Fliesstext,
       deshalb dort der helle Logo-Ton. Als FLAECHE steht im Dunkeln
       #6a58e6 (Anfang des Knopf-Verlaufs): weisse Schrift darauf misst
       rund 5:1, auf #7C6AF5 nur 4,01:1 (Sprunglink, frontend-pruefer 25.09.). Fuer Raender und accent-color bleibt
       --accent richtig. */
    --accent-text: #5646C4;
    /* Markenlila als SCHRIFT (Abschnittsnummern der Rechtsseiten, 25.09.2026).
       Logo-Familie wie der Akzent, aber als eigene Stufe fuer Ziffern und
       Auszeichnungen; Messwerte stehen in melucio-recht.css. */
    --brand-text: #6355D0;

    /* ---- Akzent als Flaeche und Linie (halbdurchsichtig) ---- */
    --accent-fill-faint: rgba(99, 85, 208, 0.06);
    --accent-fill-soft: rgba(99, 85, 208, 0.09);
    --accent-fill-strong: rgba(99, 85, 208, 0.13);
    --accent-line-faint: rgba(99, 85, 208, 0.20);
    --accent-line-soft: rgba(99, 85, 208, 0.28);
    --accent-line-strong: rgba(99, 85, 208, 0.38);

    /* ---- Neutrale Linien und Flaechen ---- */
    --line: rgba(20, 20, 45, 0.10);
    --line-2: rgba(20, 20, 45, 0.13);
    --line-3: rgba(20, 20, 45, 0.18);
    /* Alias fuer die Rechtsseiten. */
    --border: rgba(20, 20, 45, 0.13);
    --surface-soft: rgba(20, 20, 45, 0.05);
    --surface-soft-hover: rgba(20, 20, 45, 0.09);
    --underline-soft: rgba(20, 20, 45, 0.30);

    /* ---- Kopfleiste, Untergrund-Schimmer, Overlay ---- */
    --header-bg: rgba(246, 246, 251, 0.85);
    --glow-1: rgba(124, 106, 245, 0.10);
    --glow-2: rgba(110, 116, 132, 0.08);
    --overlay: rgba(18, 18, 32, 0.55);

    /* ---- Schatten ---- */
    --shadow-card: 0 20px 60px rgba(20, 20, 45, 0.14);
    --shadow-card-sm: 0 20px 40px rgba(20, 20, 45, 0.12);
    --shadow-accent: 0 10px 30px rgba(63, 47, 158, 0.25);
    --shadow-drawer: 12px 0 40px rgba(20, 20, 45, 0.18);
    --shadow-pop: 0 6px 20px rgba(20, 20, 45, 0.12);
    --shadow-chat: 0 16px 48px rgba(20, 20, 45, 0.26);
    --shadow-cta: 0 8px 24px rgba(63, 47, 158, 0.28);

    /* ---- Zustandsfarben ----
       Gemessen auf --bg-card: --ok 5,0:1, --danger-text 6,5:1.
       #43e97b und #ef4444 (die dunklen Werte) kaemen auf 1,7:1 bzw. 3,8:1. */
    /* #15803d mass auf der eigenen 10%-Fuellung nur 4,39:1 — knapp
       daneben ist daneben. #166534 kommt dort auf 6,1:1. */
    --ok: #166534;
    --ok-soft: rgba(22, 101, 52, 0.10);
    --ok-line: rgba(22, 101, 52, 0.28);
    --danger-text: #b91c1c;
    /* Warnton. Gelb traegt auf Weiss nicht: #e6b800 (der dunkle Wert) misst
       dort 1,6:1, deshalb im Hellen ein Ocker. */
    --warn-text: #7a5c00;
    --warn-soft: rgba(122, 92, 0, 0.09);
    --warn-line: rgba(122, 92, 0, 0.28);

    /* ---- Verlaeufe ----
       Fuellungen mit weisser Schrift/Icon darauf; sie sind in beiden
       Fassungen gleich, weil ihr Untergrund der Verlauf selbst ist. */
    --gradient-1: linear-gradient(135deg, #6a58e6 0%, #3F2F9E 100%);
    --gradient-2: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
    --gradient-3: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
    --gradient-4: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
    --gradient-khai: linear-gradient(135deg, #5CB85C 0%, #38f9d7 100%);
    /* Verlauf als SCHRIFT (Wortmarke, Hero-Zeile) — der steht auf dem
       Seitengrund und braucht deshalb eine eigene, dunklere Fassung.
       #667eea auf Weiss misst 3,0:1 und liegt damit auf der Kante. */
    --gradient-text: linear-gradient(135deg, #6355D0 0%, #4A36A8 100%);

    /* ---- Fokusring ---- */
    --focus-ring: #4A36A8;

    /* ---- <melucio-a11y> ---- */
    --a11y-surface: #ffffff;
    --a11y-fg: #15151f;
    --a11y-fg-muted: #55556a;
    --a11y-line-strong: rgba(20, 20, 45, 0.22);
    --a11y-accent: #6355D0;
    --a11y-accent-strong: #4A36A8;
    --a11y-accent-soft: rgba(99, 85, 208, 0.12);
    --a11y-shadow: 0 12px 34px rgba(20, 20, 45, 0.22);

    /* ---- Hoher Kontrast (a11y-Menue, data-contrast='high') ---- */
    --hc-text: #000000;
    --hc-text-muted: #22222c;
    --hc-accent: #3F2F9E;
    /* Schrift auf der Akzentflaeche im hohen Kontrast. Im Dunkeln kippt der
       Akzent dort ins Helle (#aab2ff), und weisse Schrift darauf misst 2:1 —
       gemessen am Sprunglink und am Senden-Knopf von /ki-demo. */
    --hc-on-accent: #ffffff;
    --hc-accent-hover: #33257f;
    --hc-line: rgba(0, 0, 0, 0.42);
    /* Das Gruen der Haken und Plaketten. Im Hellen hing es als einziges im
       hohen Kontrast bei 6,12:1 fest, waehrend der Rest auf 14:1 sprang. */
    --hc-ok: #0a3d1e;

    /* ---- Startseite: Material aus dem Logo (25.09.2026) ----
       Das Logo ist ein Zahnrad aus Chrom mit lila Buchstaben. Lila bleibt
       die einzige Farbe; Strich und Zahnrad im Hero tragen das Metall. */
    --chrom: #8a8fa0;
    --zahnrad: rgba(110, 116, 132, 0.13);
    --protokoll-bg: rgba(99, 85, 208, 0.05);
    --protokoll-line: rgba(99, 85, 208, 0.22);
}

/* ===== DUNKEL, Block 1 von 2: System sagt dunkel und der Besucher hat
   nichts anderes gewaehlt. ================================================ */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;
        --bg: #0e1014;
        --bg-card: #161a20;
        --surface: #161a20;
        --surface-2: #1b1f26;
        --text: #f2f3f5;
        --text-muted: #a4a9b4;
        --muted: #a4a9b4;
        --on-accent: #ffffff;
        --on-gradient: #ffffff;
        --on-gradient-hell: #15151f;
        --accent: #6a58e6;
        --accent-hover: #A99EF8;
        --accent-text: #A99EF8;
        --brand-text: #A99EF8;
        --accent-fill-faint: rgba(124, 106, 245, 0.08);
        --accent-fill-soft: rgba(124, 106, 245, 0.10);
        --accent-fill-strong: rgba(124, 106, 245, 0.15);
        --accent-line-faint: rgba(124, 106, 245, 0.18);
        --accent-line-soft: rgba(124, 106, 245, 0.26);
        --accent-line-strong: rgba(124, 106, 245, 0.32);
        --line: rgba(200, 210, 225, 0.07);
        --line-2: rgba(200, 210, 225, 0.10);
        --line-3: rgba(200, 210, 225, 0.15);
        --border: rgba(200, 210, 225, 0.11);
        --surface-soft: rgba(200, 210, 225, 0.05);
        --surface-soft-hover: rgba(200, 210, 225, 0.10);
        --underline-soft: rgba(200, 210, 225, 0.28);
        --header-bg: rgba(14, 16, 20, 0.82);
        --glow-1: rgba(124, 106, 245, 0.12);
        --glow-2: rgba(138, 143, 160, 0.08);
        --overlay: rgba(0, 0, 0, 0.80);
        --shadow-card: 0 20px 60px rgba(0, 0, 0, 0.30);
        --shadow-card-sm: 0 20px 40px rgba(0, 0, 0, 0.30);
        --shadow-accent: 0 10px 30px rgba(0, 0, 0, 0.45);
        --shadow-drawer: 12px 0 40px rgba(0, 0, 0, 0.50);
        --shadow-pop: 0 6px 20px rgba(0, 0, 0, 0.18);
        --shadow-chat: 0 16px 48px rgba(0, 0, 0, 0.60);
        --shadow-cta: 0 8px 24px rgba(0, 0, 0, 0.45);
        --ok: #43e97b;
        --ok-soft: rgba(67, 233, 123, 0.12);
        --ok-line: rgba(67, 233, 123, 0.25);
        --danger-text: #ff9494;
        --warn-text: #e6b800;
        --warn-soft: rgba(255, 193, 7, 0.08);
        --warn-line: rgba(255, 193, 7, 0.25);
        --gradient-1: linear-gradient(135deg, #6a58e6 0%, #3F2F9E 100%);
        --gradient-2: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
        --gradient-3: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
        --gradient-4: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
        --gradient-khai: linear-gradient(135deg, #5CB85C 0%, #38f9d7 100%);
        --gradient-text: linear-gradient(135deg, #A99EF8 0%, #C4B5FD 100%);
        --focus-ring: #A99EF8;
        --a11y-surface: #181c23;
        --a11y-fg: #ffffff;
        --a11y-fg-muted: #b9b9c6;
        --a11y-line-strong: rgba(255, 255, 255, 0.20);
        --a11y-accent: #6a58e6;
        --a11y-accent-strong: #C4B5FD;
        --a11y-accent-soft: rgba(124, 106, 245, 0.18);
        --a11y-shadow: 0 12px 34px rgba(0, 0, 0, 0.55);
        --hc-text: #ffffff;
        --hc-text-muted: #e8e8f0;
        --hc-accent: #C4B5FD;
        --hc-on-accent: #15151f;
        --hc-accent-hover: #ddd6fe;
        --hc-line: rgba(255, 255, 255, 0.34);
        /* Im Dunkeln misst --ok schon 12,1:1 — hier gibt es nichts zu heben. */
        --hc-ok: #43e97b;
        --chrom: #9aa0b0;
        --zahnrad: rgba(160, 166, 182, 0.11);
        --protokoll-bg: rgba(124, 106, 245, 0.07);
        --protokoll-line: rgba(124, 106, 245, 0.26);
    }
}

/* ===== DUNKEL, Block 2 von 2: der Besucher hat dunkel gewaehlt.
   Wortgleich zu Block 1 — siehe pruefe-themebloecke.mjs. ================== */
:root[data-theme="dark"] {
    color-scheme: dark;
    --bg: #0e1014;
    --bg-card: #161a20;
    --surface: #161a20;
    --surface-2: #1b1f26;
    --text: #f2f3f5;
    --text-muted: #a4a9b4;
    --muted: #a4a9b4;
    --on-accent: #ffffff;
    --on-gradient: #ffffff;
    --on-gradient-hell: #15151f;
    --accent: #6a58e6;
    --accent-hover: #A99EF8;
    --accent-text: #A99EF8;
    --brand-text: #A99EF8;
    --accent-fill-faint: rgba(124, 106, 245, 0.08);
    --accent-fill-soft: rgba(124, 106, 245, 0.10);
    --accent-fill-strong: rgba(124, 106, 245, 0.15);
    --accent-line-faint: rgba(124, 106, 245, 0.18);
    --accent-line-soft: rgba(124, 106, 245, 0.26);
    --accent-line-strong: rgba(124, 106, 245, 0.32);
    --line: rgba(200, 210, 225, 0.07);
    --line-2: rgba(200, 210, 225, 0.10);
    --line-3: rgba(200, 210, 225, 0.15);
    --border: rgba(200, 210, 225, 0.11);
    --surface-soft: rgba(200, 210, 225, 0.05);
    --surface-soft-hover: rgba(200, 210, 225, 0.10);
    --underline-soft: rgba(200, 210, 225, 0.28);
    --header-bg: rgba(14, 16, 20, 0.82);
    --glow-1: rgba(124, 106, 245, 0.12);
    --glow-2: rgba(138, 143, 160, 0.08);
    --overlay: rgba(0, 0, 0, 0.80);
    --shadow-card: 0 20px 60px rgba(0, 0, 0, 0.30);
    --shadow-card-sm: 0 20px 40px rgba(0, 0, 0, 0.30);
    --shadow-accent: 0 10px 30px rgba(0, 0, 0, 0.45);
    --shadow-drawer: 12px 0 40px rgba(0, 0, 0, 0.50);
    --shadow-pop: 0 6px 20px rgba(0, 0, 0, 0.18);
    --shadow-chat: 0 16px 48px rgba(0, 0, 0, 0.60);
    --shadow-cta: 0 8px 24px rgba(0, 0, 0, 0.45);
    --ok: #43e97b;
    --ok-soft: rgba(67, 233, 123, 0.12);
    --ok-line: rgba(67, 233, 123, 0.25);
    --danger-text: #ff9494;
    --warn-text: #e6b800;
    --warn-soft: rgba(255, 193, 7, 0.08);
    --warn-line: rgba(255, 193, 7, 0.25);
    --gradient-1: linear-gradient(135deg, #6a58e6 0%, #3F2F9E 100%);
    --gradient-2: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
    --gradient-3: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
    --gradient-4: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
    --gradient-khai: linear-gradient(135deg, #5CB85C 0%, #38f9d7 100%);
    --gradient-text: linear-gradient(135deg, #A99EF8 0%, #C4B5FD 100%);
    --focus-ring: #A99EF8;
    --a11y-surface: #181c23;
    --a11y-fg: #ffffff;
    --a11y-fg-muted: #b9b9c6;
    --a11y-line-strong: rgba(255, 255, 255, 0.20);
    --a11y-accent: #6a58e6;
    --a11y-accent-strong: #C4B5FD;
    --a11y-accent-soft: rgba(124, 106, 245, 0.18);
    --a11y-shadow: 0 12px 34px rgba(0, 0, 0, 0.55);
    --hc-text: #ffffff;
    --hc-text-muted: #e8e8f0;
    --hc-accent: #C4B5FD;
    --hc-on-accent: #15151f;
    --hc-accent-hover: #ddd6fe;
    --hc-line: rgba(255, 255, 255, 0.34);
    /* Im Dunkeln misst --ok schon 12,1:1 — hier gibt es nichts zu heben. */
    --hc-ok: #43e97b;
    --chrom: #9aa0b0;
    --zahnrad: rgba(160, 166, 182, 0.11);
    --protokoll-bg: rgba(124, 106, 245, 0.07);
    --protokoll-line: rgba(124, 106, 245, 0.26);
}

/* ===== Was aus den Token folgt — gilt fuer alle zwanzig Seiten ========== */

/* Kein fremdes Blau beim Markieren (CLAUDE.md, Punkt 5). */
/* melucio-reset.css faerbt jeden <a> mit `var(--primary, #5CB85C)`. Ohne
   gesetztes --primary trug das Portfolio also KHAI-Gruen in den Links — im
   Dunkeln unauffaellig (5,8:1), im Hellen mit 2,48:1 nicht mehr. Der Akzent
   der Marke ist lila ([[marke-lila-nicht-gruen]]), und --accent-text ist der
   Ton, der als SCHRIFT in beiden Fassungen traegt: --accent selbst misst im
   Dunkeln nur 4,13:1. */
:root { --primary: var(--accent-text); }

/* Farben und Schrift fuer <melucio-footer>. Ohne sie fiel der Baustein auf
   seine eigenen Vorgaben zurueck: Hover und Copyright-Link in KHAI-Gruen
   #5CB85C, Hintergrund #1A1A2E statt Graphit (design-berater 26.09.2026).
   Nur einmal auf :root, wie --primary: Die Werte sind Verweise, und die
   verwiesenen Token wechseln mit dem Theme und dem hohen Kontrast selbst.
   Gemessen stehen die Werte bei den Token: --muted auf --bg hell 6,4:1,
   --accent-text auf --bg hell 6,3:1, dunkel 7,5:1. */
:root {
    --mf-accent: var(--accent-text);
    --mf-bg: var(--bg);
    --mf-text: var(--muted);
    --mf-sep: var(--muted);
    --mf-border: var(--border);
    --mf-pill-hover: var(--accent-fill-faint);
    --mf-font: var(--body-font, 'Inter', -apple-system, BlinkMacSystemFont, sans-serif);
}

::selection { background: var(--accent); color: var(--on-accent); }

/* Hoher Kontrast aus dem a11y-Menue. Steht hier statt in jeder Seite, und
   greift auf beide Fassungen: die Werte kommen aus den Token oben. */
:root[data-contrast='high'] {
    --text-muted: var(--hc-text-muted);
    --muted: var(--hc-text-muted);
    --accent: var(--hc-accent);
    --accent-hover: var(--hc-accent-hover);
    --accent-text: var(--hc-accent);
    --brand-text: var(--hc-accent);
    --on-accent: var(--hc-on-accent);
    --line: var(--hc-line);
    --line-2: var(--hc-line);
    --line-3: var(--hc-line);
    --border: var(--hc-line);
    /* --on-gradient bleibt bewusst stehen: die Verlaeufe kippen nicht mit. */

    /* Der Schalter steht IM a11y-Menue — und liess ausgerechnet dieses Menue
       unveraendert (Davids Beobachtung 22.09.2026 an zwei Bildschirmfotos,
       auf denen "Normal" und "Hoch" gleich aussehen). Jetzt zieht es mit. */
    --a11y-fg: var(--hc-text);
    --a11y-fg-muted: var(--hc-text-muted);
    --a11y-line-strong: var(--hc-line);
    --a11y-accent: var(--hc-accent);
    --a11y-accent-strong: var(--hc-accent-hover);
    --ok: var(--hc-ok);
}
:root[data-contrast='high'] body { color: var(--hc-text); }

/* Im hohen Kontrast gibt es keine Verlaufsschrift. Ein Verlauf kann seine
   Helligkeit nicht wechseln; er bliebe stehen, waehrend alles um ihn herum
   auf 15:1 springt — und faellt dann als DIE dunkle Stelle auf. Gemessen im
   Dunkeln: der Verlauf haelt 3,04:1 am dunklen Ende, der Ersatz 9,84:1. */
:root[data-contrast='high'] .logo-text,
:root[data-contrast='high'] .hero h1 .gradient,
:root[data-contrast='high'] .page-h1 .gradient,
:root[data-contrast='high'] .lp-header .brand {
    background: none;
    -webkit-text-fill-color: var(--accent-text);
    color: var(--accent-text);
}

/* Das a11y-Menue holt seine Farben aus den Token, statt sie je Seite
   noch einmal fest zu setzen. */
melucio-a11y {
    --surface: var(--a11y-surface);
    --fg: var(--a11y-fg);
    --fg-muted: var(--a11y-fg-muted);
    --line-strong: var(--a11y-line-strong);
    --accent: var(--a11y-accent);
    --accent-strong: var(--a11y-accent-strong);
    --accent-soft: var(--a11y-accent-soft);
    --shadow: var(--a11y-shadow);
}

/* Die beiden Kreise rechts im Kopf sehen gleich aus: dieselbe Groesse,
   dieselbe Rahmen- und Symbolfarbe, dasselbe Hover. Bis zum 25.09.2026 trug
   der a11y-Kreis ein Lila-Symbol (--a11y-accent-strong) und einen
   kraeftigeren Rand (0.22 statt 0.18) als der Theme-Kreis daneben und wuchs
   bei groesserer Schrift mit, der Theme-Kreis nicht. Die Werte stehen EINMAL
   hier, beide Knoepfe lesen sie. Symbol in Textfarbe: so kraeftig wie der
   Text (gemessen 16,8:1 hell, 17,2:1 dunkel auf dem Kopf). */
:root {
    --kopf-kreis-rand: var(--line-3);
    --kopf-kreis-symbol: var(--text);
    --kopf-kreis-hover: var(--surface-soft-hover);
    --kopf-kreis-mass: 40px;
}
@media (pointer: coarse) {
    :root { --kopf-kreis-mass: 44px; }
}
@media (max-width: 479px) {
    :root { --kopf-kreis-mass: 36px; }
}
@media (max-width: 479px) and (pointer: coarse) {
    :root { --kopf-kreis-mass: 44px; }
}
melucio-a11y {
    --a11y-toggle-size: var(--kopf-kreis-mass);
    --a11y-toggle-color: var(--kopf-kreis-symbol);
    --a11y-toggle-border: var(--kopf-kreis-rand);
    --a11y-toggle-hover-border: var(--kopf-kreis-rand);
    --a11y-toggle-hover-bg: var(--kopf-kreis-hover);
}

/* Der Umschalter im Kopf: runder Knopf, Tap-Flaeche 44px in PIXELN
   (CLAUDE.md — die Wurzelschrift dieser Seite ist fliessend). */
melucio-theme-toggle {
    --theme-toggle-color: var(--kopf-kreis-symbol);
    --theme-toggle-border: var(--kopf-kreis-rand);
    --theme-toggle-hover-bg: var(--kopf-kreis-hover);
    /* In Pixeln, weil die Wurzelschrift dieser Seite fliessend ist; das
       Mass steht mit den Stufen oben unter --kopf-kreis-mass. */
    --theme-toggle-size: var(--kopf-kreis-mass);
}

/* Der Chat-Knopf (seit 17.10.2026 NICHT mehr im Kopf, Davids Vorgabe: Knopf-
   Stapel, Grundmuster 3). Er steht am Ende des <body> und sitzt als runder
   Knopf unten rechts, Nach-oben darueber; Stellung und Abstand liefert
   melucio-fab-stapel.css (.fab-stapel-chat). Hier nur Mass und Optik.
   Vorher stand er als eckiger Knopf neben dem Menue; mobil war der Kopf mit
   Menue, Chat, Lockup und zwei Kreisen zu eng.

   Zwei Formen im Kopf bleiben: links der abgerundete Eckknopf (Menue, fuehrt
   woandershin), rechts Kreise (a11y, Theme, aendern die Darstellung). Der
   Chat oeffnet ein Fenster ueber der Seite, ist also ein schwebender Knopf
   und kein Teil dieser Reihen.

   Mass: 46px (wie Nach-oben), am Finger nie unter 44. */
:root {
    --fab-rand: 20px;
    --fab-bot-h: 46px;
    --fab-luft: 10px;
}
@media (max-width: 480px) {
    :root { --fab-rand: 16px; }
}
.mlx-chat-trigger{display:inline-flex;align-items:center;justify-content:center;flex:none;cursor:pointer;padding:0}
.mlx-chat-trigger svg{width:22px;height:22px}
.mlx-chat-trigger.fab-stapel-chat {
    border: 1px solid var(--accent-text);
    background: var(--bg);
    color: var(--accent-text);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
    transition: background .18s ease, border-color .18s ease;
}
.mlx-chat-trigger.fab-stapel-chat:hover {
    background: var(--surface-soft-hover);
}
.mlx-chat-trigger.fab-stapel-chat:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}
@media (prefers-reduced-motion:reduce){
    .mlx-chat-trigger.fab-stapel-chat { transition: none; }
}
.header-links .nav-toggle {
    width: 40px;
    height: 40px;
    border-radius: 12px;
    border: 1px solid var(--line-3);
    background: transparent;
    transition: background .18s ease, border-color .18s ease;
    /* Der Hamburger stand frei und zog sich mit margin:-10px wieder
       zusammen; im Rahmen wuerde dieses Minus die Nachbarn ueberlappen. */
    margin: 0;
    padding: 0;
    align-items: center;
}
.header-links .nav-toggle:hover {
    background: var(--surface-soft-hover);
    border-color: var(--accent-line-soft);
}
.header-links .nav-toggle:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}
@media (prefers-reduced-motion:reduce){
    .header-links .nav-toggle { transition: none; }
}
/* ── Die Kopfzeile in drei Spalten ──────────────────────────────────────

   Links die Navigation (Menue), in der Mitte das Lockup, rechts die
   Darstellungs-Sachen (a11y, Theme, spaeter der Sprachwechsel). Genau die
   Aufteilung verlangt die CLAUDE.md unter Punkt 2, und das Portfolio hielt
   sich bis zum 22.09.2026 nicht daran: Der Hamburger stand rechts zwischen
   den Anzeige-Knoepfen. Vorbild ist die Topbar von M.d.Ae.

   `1fr auto 1fr` statt `justify-content: space-between`: So bleibt das
   Lockup wirklich mittig, egal wie viele Knoepfe links und rechts stehen.
   M.d.Ae. loest dieselbe Aufgabe mit einem `.topbar-spacer`, der von Hand
   mitwachsen muss — steht sein Kommentar daneben („Muss mit den Knoepfen
   mitwachsen, sonst sitzt das Logo aus der Mitte"). Mit dem Raster entfaellt
   die Pflege: Spalte 1 und 3 sind per Definition gleich breit, und die drei
   Zonen liegen fest auf ihrer Spalte. Eine Seite ohne Menue (die
   Videoraum-Seiten) braucht deshalb auch keinen Platzhalter.

   Die Schublade steht in .header-links direkt hinter dem Menueknopf (damit
   Tab nach dem Oeffnen in die Menuepunkte geht) und ist `position: fixed`;
   sie faellt damit aus der Knopfreihe heraus und belegt keinen Platz. Ab
   1024px loest melucio-nav.css die Gruppe auf und stellt sie ins Raster. */
.header-content,
.lp-header {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 12px;
}
.header-links {
    grid-column: 1;
    justify-self: start;
    display: flex;
    align-items: center;
    gap: 12px;
}
.header-content > .logo,
.lp-header > .logo {
    grid-column: 2;
    justify-self: center;
}
.header-controls {
    grid-column: 3;
    justify-self: end;
    display: flex;
    align-items: center;
    gap: 12px;
}
@media (max-width: 413px) {
    /* Enger ruecken, aber NICHT unter die Tap-Flaeche: die Knoepfe behalten
       ihre 44px am Finger, nur der Abstand dazwischen gibt nach. */
    .header-content,
    .lp-header { gap: 6px; }
    .header-links,
    .header-controls { gap: 6px; }
}

/* Tap-Flaechen der linken Gruppe. Gemessen am 22.09.2026 bei 375px mit
   Touch-Emulation: Menue 42x36, Chat 38x38 — beide unter den 44px, die die
   CLAUDE.md verlangt, und beide schon vorher so. Neben den 44px-Kreisen von
   a11y und Theme fiel es erst auf, als die vier Knoepfe in zwei Gruppen
   auseinandergingen. Untergrenze in PIXELN, nicht in rem: die Wurzelschrift
   dieser Seite ist fliessend und faellt auf schmalen Fenstern auf 15px. */
@media (pointer: coarse) {
    .header-links .nav-toggle {
        min-width: 44px;
        min-height: 44px;
    }
}
/* ── Das Lockup ─────────────────────────────────────────────────────────
   Stand bis zum 22.09.2026 in melucio-site.css, die sieben Rechtsseiten und
   die Videoraum-Seiten laden die aber nicht: Dort war das Logo blanker
   36px-Zahn ohne Wortmarke, waehrend die Hauptseiten Zahn plus Wortmarke
   zeigten. Beim Seitenwechsel auf dem Telefon sprang das sofort ins Auge
   (Davids Fund). Jetzt tragen alle einundzwanzig dasselbe. */
.logo {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
}
.logo-img {
    height: 42px;
    width: auto;
    /* KEIN Rahmen, keine Kachel (Davids Vorgabe 06.09.2026): das Logo steht
       frei auf dem Grund. Fuer dunkle Flaechen liefert der Header die
       Silber-ML-Fassung (leite-ab.py, zweiter Master). */
}
.logo-text {
    font-size: 1.75rem;
    font-weight: 700;
    background: var(--gradient-text);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}
@media (max-width: 768px) {
    .logo { gap: 8px; }
    .logo-img { height: 34px; }
    .logo-text { font-size: 1.35rem; }
}
@media (max-width: 480px) {
    .logo-img { height: 30px; }
    .logo-text { font-size: 1.18rem; }
}
@media (max-width: 413px) {
    .logo { min-width: 0; }
    .logo-img { height: 26px; }
    .logo-text { font-size: 1rem; }
}
/* Unter 380px weicht die Wortmarke dem Symbol. Nachgerechnet bei 320px:
     nach den Seitenraendern bleiben 272px, und die vier Bedienknoepfe belegen
     davon 186 (44 + 44 + 38 + 42 plus dreimal 6 Abstand) — fuer das Lockup
     bleiben 86, und 26px Symbol plus Abstand lassen davon 52 fuer elf
     Buchstaben. Bis zum 22.09.2026 waren es drei Knoepfe und es ging knapp auf;
     mit dem Theme-Umschalter geht es nicht mehr. Der Name bleibt im alt-Text
     des Logos und damit im Zugaenglichkeitsbaum, die Tap-Flaeche des Links
     bleibt ueber .logo-img + Rand erhalten. */
@media (max-width: 359px) {
    .logo-text { display: none; }
}
/* Dasselbe, wenn die Kopfzeile nachgemessen nicht passt (navigation.js
   setzt kopf-eng, etwa bei vergroesserter Schrift aus dem a11y-Menue). */
:root.kopf-eng .logo-text { display: none; }

/* Die Rechtsseiten nennen ihr Lockup nicht immer .logo; der Link zur
   Startseite ist dort das einzige <a> im Kopf. */
.lp-header > a:not(.logo) {
    grid-column: 2;
    justify-self: center;
}

/* ── Die Icon-Kacheln ───────────────────────────────────────────────────
   Bis zum 22.09.2026 stand der Verlauf als style-Attribut an jeder Kachel,
   und das Zeichen darin war immer weiss. Auf den vier hellen Verlaeufen war
   es damit praktisch unsichtbar (1,34 bis 2,41:1). Mit einer Klasse je
   Verlauf steht beides beieinander: die Flaeche und das, was darauf traegt. */
.icon-violet { background: var(--gradient-1); color: var(--on-gradient); }
.icon-pink   { background: var(--gradient-2); color: var(--on-gradient-hell); }
.icon-blue   { background: var(--gradient-3); color: var(--on-gradient-hell); }
.icon-green  { background: var(--gradient-4); color: var(--on-gradient-hell); }
.icon-khai   { background: var(--gradient-khai); color: var(--on-gradient-hell); }
/* Eine Farbe statt fuenf (Startseite, 25.09.2026): ruhige lila Flaeche, das
   Zeichen in --accent-text. Den vollen Verlauf (.icon-violet) tragen nur die
   Kernleistungen; so entsteht Gewichtung ohne neue Farbe, und das KHAI-Gruen
   verschwindet von der Seite, auf der es nie hingehoerte. */
.icon-mono {
    background: var(--accent-fill-strong);
    color: var(--accent-text);
    box-shadow: inset 0 0 0 1px var(--accent-line-faint);
}

/* ── Seitenraender als Variablen (CLAUDE.md Punkt 4) ────────────────────
   Bis zum 25.09.2026 stand der Rand als Zahl an jeder Stelle: 24px im
   .container, im Kopf und in den Brotkrumen, 20px auf den Rechtsseiten.
   Gestaffelt wie in apps/widab-landing/src/styles/theme.css: Bilder am
   dichtesten an der Kante, Fliesstext dahinter, Karten leicht eingerueckt.
   "Enger" oder "weiter" ist damit eine Zeile.

   Verdrahtet ist bisher nur --gutter-text: Die Site hat keine Bilder, die
   naeher an der Kante stehen als der Text, und keine Karten, die gegen ihn
   eingerueckt sind — alles sitzt im .container. Die beiden anderen stehen
   bereit fuer das erste Element, das eine davon braucht, damit es dann
   keine eigene Zahl bekommt. */
:root {
    --gutter-media: 16px;
    --gutter-text: 24px;
    --gutter-card: 28px;
}
/* Abstands-Staffel, dieselben Stufen wie im geteilten Theme
   (packages/@meluciolabs/ui-components/src/theme/melucio-theme.css), das
   diese Site nicht laedt. In rem, damit sie mit der Schriftgroesse aus dem
   a11y-Menue mitwaechst. Erster Nutzer: die Teilen-Zeile (26.09.2026). */
:root {
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;
    --spacing-2xl: 3rem;
}
@media (max-width: 479px) {
    :root {
        --gutter-media: 12px;
        --gutter-text: 20px;
        --gutter-card: 22px;
    }
}

/* ── Anker unter dem festen Kopf (CLAUDE.md Punkt 1) ───────────────────
   Ohne das verschwindet jedes Sprungziel unter der Leiste, zuletzt #stufen
   auf der Sicherheitspruefungs-Seite (Fullscan 25.09.2026). --header-h
   misst navigation.js am echten Kopf.

   Zwei Teile, die sich ADDIEREN: scroll-padding am <html> haelt die
   Kopfhoehe frei, fuer Anker UND fuer den Tastaturfokus (WCAG 2.4.11,
   beim Rueckwaerts-Tab lag der Link sonst unter der Leiste). Die [id]-Regel
   gibt nur noch die Luft von 0.8rem dazu. Standen beide mit voller
   Kopfhoehe da, landete ein Anker rund 110px unter dem Kopf (25.09.2026). */
html { scroll-padding-top: var(--header-h, 78px); }
[id] { scroll-margin-top: 0.8rem; }

/* ── Sprunglink (alle Seiten) ────────────────────────────────────────────
   Stand bis zum 25.09.2026 nur auf der Startseite, in melucio-site.css —
   die die Rechtsseiten gar nicht laden. Unsichtbar, bis er per Tastatur
   den Fokus bekommt; wer mit Tab navigiert, springt damit am Kopf vorbei. */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 200;
    padding: 10px 16px;
    background: var(--accent);
    color: var(--on-accent);
    border-radius: 0 0 8px 0;
    font-weight: 600;
    text-decoration: none;
}
.skip-link:focus { left: 0; }
/* Das Sprungziel bekommt den Fokus nur voruebergehend (tabindex="-1");
   ein Ring um den ganzen Inhalt waere nur Laerm. */
main:focus { outline: none; }

/* ── Links im Fliesstext sind unterstrichen ─────────────────────────────
   Nur ueber die Farbe erkennbar waren sie zum umgebenden Text 1,1:1
   (Fullscan 25.09.2026, WCAG 1.4.1). Gemeint sind Links MITTEN im Satz:
   ohne eigene Klasse, in Absatz, Aufzaehlung oder Tabelle. Knoepfe,
   Karten und Menues tragen eine Klasse oder stehen woanders. */
main p a:not([class]),
main li a:not([class]),
main dd a:not([class]),
main td a:not([class]) {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

/* Nur fuer Vorlesehilfen (Live-Ansagen, Zusatzhinweise wie „oeffnet in
   neuem Fenster"). */
.visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Teilen-Knopf am Seitenende (CLAUDE.md Punkt 12, assets/js/teilen.js).
   Der Abstand kommt aus der Abstands-Staffel oben, nicht als Zahl.
   `body .teilen-zeile` statt nur `.teilen-zeile`: Auf zwoelf der dreizehn
   Seiten traegt die Zeile auch `.container`, und dessen `padding: 0 …` in
   melucio-site.css (spaeter geladen, gleiche Spezifitaet) nahm ihr bis zum
   26.09.2026 jeden Abstand. Gemessen klebte der Knopf mobil 22px, am
   Desktop 38px unter den Knoepfen darueber und direkt auf dem Fuss. */
body .teilen-zeile {
    display: flex;
    justify-content: center;
    padding-top: var(--spacing-xl);
    padding-bottom: var(--spacing-xl);
}
.teilen-knopf {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
}

/* Nettopreis neben dem Bruttopreis (Davids Entscheid 25.09.2026: brutto
   vorn, netto direkt daneben, kaum kleiner, kein Umschalter). 2px unter der
   Umgebung und nie unter 14px; Farbe ist die Fliesstextfarbe --text-muted,
   ohne opacity, damit der Kontrast in hell und dunkel ueber 4,5:1 bleibt.
   Die Preisseite setzt dieselbe Regel in ihrem Erzeuger. */
.netto {
    color: var(--text-muted);
    font-size: max(14px, calc(1em - 2px));
    font-weight: 400;
    white-space: nowrap;
}

/* ── Ueberschriften-Schrift (alle Seiten) ────────────────────────────────
   Bricolage Grotesque, Davids Wahl vom 25.09.2026 aus vier Proben. Selbst
   gehostet, OFL (fonts/bricolage-grotesque-OFL.txt), nur latin: deckt
   Umlaute und ß ab, 41 kB. Stand zuerst nur in melucio-site.css, die die
   Rechtsseiten nicht laden; hier ist sie EINMAL definiert, und beide
   Stylesheets nutzen --heading-font. Fliesstext bleibt, was er war.
   Waehlt jemand im a11y-Menue eine Leseschrift (--body-font), gilt sie
   auch fuer Ueberschriften: var(--body-font, var(--heading-font)). */
@font-face {
    font-family: 'Bricolage Grotesque';
    font-style: normal;
    font-weight: 200 800;
    font-display: swap;
    src: url('/fonts/bricolage-grotesque-latin.woff2?v=202610201757') format('woff2');
    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 {
    --heading-font: 'Bricolage Grotesque', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}

/* Inter fuer den Fliesstext, self-hosted (latin + latin-ext, variable
   Staerke 300 bis 700). Stand bis zum 26.09.2026 nur in melucio-site.css,
   die Rechtsseiten, 404 und /v/termin nicht laden: deren Fliesstext lief
   deshalb in der Systemschrift (Kontroll-Rundgang 26.09.2026). Jetzt hier,
   EINMAL, wie Bricolage. Die Adressen samt ?v=202610201757 muessen wortgleich zu den
   preload-Zeilen im <head> der Seiten bleiben (seit 26.09.2026 inter-latin
   und bricolage-grotesque-latin, auf /preise nur inter-latin), sonst laedt der
   Browser die Datei doppelt. Der Deploy ersetzt ?v=202610201757 in HTML und CSS mit
   demselben Zeitstempel. */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url('/fonts/inter-latin-ext.woff2?v=202610201757') format('woff2');
    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: 'Inter';
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url('/fonts/inter-latin.woff2?v=202610201757') format('woff2');
    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;
}

/* ── Aus melucio-breakpoints.css uebernommen (26.09.2026) ──────────────
   Die Seiten luden die geteilte Staffel als eigenes Stylesheet, genutzt
   wurde davon nichts: keine ihrer Klassen, keine ihrer Variablen (Suche
   ueber apps/meluciolabs). Wirksam waren nur die zwei globalen Bloecke
   hier unten, und die stehen jetzt in dieser Datei, die jede Seite ohnehin
   laedt. Ein render-blockierender Abruf weniger. Die Staffel bleibt die
   Quelle fuer Breakpoints
   (packages/@meluciolabs/ui-components/src/theme/melucio-breakpoints.css).

   Weniger Bewegung per Systemeinstellung: melucio-site.css hat dafuer
   einen eigenen, strengeren Block, die Rechtsseiten, 404 und /v/termin
   laden sie aber nicht. Dieselbe Regel wie der Schalter in
   melucio-a11y.css (data-motion), nur unter der Media Query. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}
@media print {
    body { background: white !important; color: black !important; }
}

/* components/melucio-nav.css */
/* Das Menue von meluciolabs.de, als eigene Datei.

   Bis zum 14.09.2026 standen diese Regeln in melucio-site.css. Die
   Rechtsseiten (Impressum, Datenschutz, AGB, Widerruf, Sicherheitshinweise,
   404) koennen diese Datei aber nicht laden: Sie setzt body, header und
   .container fuer das Layout der Hauptseiten und wuerde die schlanken
   Rechtsseiten zerlegen. Als die auch ein Menue bekommen sollten, war die
   Wahl: dieselben neunzig Zeilen ein zweites Mal pflegen, oder einmal.

   Deshalb liegt das Menue jetzt hier und wird von ALLEN zwanzig Seiten
   geladen. Wer eine Regel aendert, aendert sie an einer Stelle.

   Die Rueckfaelle in var() sind kein Zufall: Die Hauptseiten kennen
   --text-muted und --accent-hover, die Rechtsseiten --muted und --accent.
   Ohne den zweiten Wert waere die Schrift dort schwarz auf schwarz. */


        /* Hamburger toggle — always visible (Desktop + Mobile) */
        .nav-toggle {
            display: flex;
            flex-direction: column;
            justify-content: center;
            gap: 5px;
            background: none;
            border: none;
            padding: 10px;
            cursor: pointer;
            margin: -10px;
            position: relative;
            z-index: 101;
            -webkit-tap-highlight-color: transparent;
            outline: none;
        }
        .nav-toggle:focus-visible {
            outline: 2px solid var(--focus-ring, var(--accent));
            outline-offset: 2px;
        }
        .nav-toggle span {
            display: block;
            /* Die Breite steht hier FEST und nicht als Dehnung des
               Flex-Vaters. /ki-demo hatte eine eigene span-Regel ohne Breite
               und lebte davon, dass align-items auf stretch stand; mit dem
               Rahmen um den Knopf (align-items: center) waren die Balken
               ploetzlich null Pixel breit — ein leeres Viereck im Kopf
               (Davids Bildschirmfoto 22.09.2026). Die eigene Regel ist weg,
               diese traegt jetzt allein. */
            width: 22px;
            flex: none;
            height: 2px;
            background: var(--text);
            border-radius: 1px;
            transition: transform 0.3s, opacity 0.2s;
        }
        .nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
        .nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
        .nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

        /* Side-Drawer — beginnt unter dem Header, faehrt von LINKS ein.
           Bis zum 22.09.2026 kam sie von rechts; seit der Menue-Knopf nach
           links gewandert ist (CLAUDE.md, Punkt 2), muss sie mit. Ein Knopf
           links und eine Schublade am anderen Rand ist keine Bedienung. */
        .nav-links {
            position: fixed;
            top: var(--header-h, 78px);
            left: 0;
            bottom: 0;
            width: 300px;
            max-width: 86vw;
            display: flex;
            flex-direction: column;
            align-items: stretch;
            gap: 0;
            padding: 12px 0;
            background: var(--bg);
            border-right: 1px solid var(--line-2, var(--border));
            box-shadow: var(--shadow-drawer);
            transform: translateX(-100%);
            /* Zugeklappt heisst auch fuer die Tastatur weg (CLAUDE.md): Ein
               blosses translateX schiebt die Schublade nur aus dem Bild, ihre
               Links bleiben fokussierbar. Wer mit Tab durch die Seite geht,
               wandert sonst durch das komplette geschlossene Menue, waehrend
               der Fokusring ausserhalb des Fensters liegt. Die Verzoegerung
               in der Transition haelt die Leiste waehrend des Ausfahrens
               sichtbar. */
            visibility: hidden;
            transition: transform 0.3s ease, visibility 0s linear 0.3s;
            z-index: 99;
            overflow-y: auto;
        }
        .nav-links.open { transform: translateX(0); visibility: visible; transition: transform 0.3s ease, visibility 0s; }

        .nav-links a {
            display: block;
            color: var(--text-muted, var(--muted));
            text-decoration: none;
            font-size: 0.95rem;
            font-weight: 500;
            text-align: left;
            padding: 8px 24px;
            transition: background 0.2s, color 0.2s;
        }
        .nav-links a:hover {
            color: var(--text);
            background: var(--surface-soft);
        }
        .nav-divider {
            display: block;
            height: 1px;
            background: var(--line-2, var(--border));
            margin: 4px 24px;
        }
        .nav-links .nav-cta {
            color: var(--accent-hover, var(--accent));
            font-weight: 600;
        }
        /* Die Rechtslinks standen bis zum 22.09.2026 auf einem festen
           rgba(255,255,255,0.5) — im hellen Modus waere das Weiss auf Weiss
           gewesen. --text-muted traegt in beiden Fassungen, die Abstufung
           gegenueber den Hauptpunkten macht jetzt die Schriftgroesse. */
        .nav-links .nav-legal {
            font-size: 0.85rem;
            color: var(--text-muted, var(--muted));
            padding: 4px 24px;
        }

        /* Auf schmalen Telefonen fuellt die Schublade mehr vom Bild. */
        @media (max-width: 768px) {
            .nav-links { width: 280px; }
        }

        /* ── Die Rechtsseiten ───────────────────────────────────────────

           Deren Kopf (.lp-header) lief bisher einfach mit dem Text nach
           oben weg. Das ging, solange dort nur "Zur Startseite" stand.
           Mit einem Menue geht es nicht: Eine Datenschutzerklaerung ist
           zwanzig Bildschirme lang, und ein Menue, das man nur ganz oben
           erreicht, ist auf Seite fuenfzehn keins. Deshalb klebt der Kopf
           dort jetzt oben, wie auf den Hauptseiten auch.

           Die 84px sind die tatsaechliche Hoehe dieses Kopfes (24px Rand
           oben und unten plus 36px Logo), nicht die 78px der Hauptseiten. */
        .lp-header {
            position: sticky;
            top: 0;
            z-index: 100;
            background: var(--bg);
        }

        /* FEST STATT KLEBEND (25.09.2026, CLAUDE.md Frontend-Grundmuster 1).
           sticky reicht fuers Mitlaufen, aber die Anker nicht: Wer auf
           datenschutz.html#reichweite sprang, landete unter dem Kopf. Jetzt
           wie auf den Hauptseiten: position fixed, vollbreit, Hoehe als
           --header-h (misst navigation.js), body rueckt um genau diese Hoehe
           ein, und [id] haelt Abstand (scroll-margin-top in
           melucio-tokens.css).
           Nur fuer Koepfe MIT Menue: v/termin.html hat keins und laedt kein
           navigation.js, also misst dort niemand die Hoehe — der Kopf bleibt
           dort klebend. Die Leiste geht ueber die volle Breite; ihr Inhalt
           steht per Polster auf derselben Lesebreite (760px) wie der Text. */
        header.lp-header:has(.nav-links) {
            position: fixed;
            left: 0;
            right: 0;
            max-width: none;
            margin: 0;
            padding-left: max(var(--gutter-text), calc((100% - 760px) / 2 + var(--gutter-text)));
            padding-right: max(var(--gutter-text), calc((100% - 760px) / 2 + var(--gutter-text)));
            border-bottom: 1px solid var(--line-2, var(--border));
        }
        body:has(> header.lp-header .nav-links) {
            padding-top: var(--header-h, 88px);
        }
/* Die Hoehe kommt aus assets/js/navigation*.js, gemessen am echten Kopf.
   Der Rueckfall gilt nur, solange das Skript nicht gelaufen ist. */

/* ── Ab 1024px liegt das Menue offen in der Leiste ────────────────────

   CLAUDE.md Punkt 2: Die Menuepunkte liegen ab etwa 1000px offen im Kopf,
   darunter klappen sie als Schublade auf. Bis zum 25.09.2026 blieb es
   auch bei 1280px eine Schublade (Fullscan).

   Die Grenze lag erst bei 1280 (`desktop`), weil sieben Punkte samt
   Lockup und vier Knoepfen rund 1060px brauchten; bei 1024 brach der Kopf
   auf 137px Hoehe um. Seit dem Menue mit fuenf Punkten (25.09.2026) passt
   es eine Stufe frueher, `laptop`: Nachgemessen bei 1024 abzueglich
   Rollbalken (1009px nutzbar) bleibt der Kopf einzeilig (86px wie
   darueber) und zwischen Lockup und erstem Menuepunkt stehen noch 162px
   Luft, auf den Rechtsseiten und der KI-Demo 190px.

   Das gilt nur bei normaler Schrift. Bei 1024 hielt die Leiste bis 137,5 %
   aus dem a11y-Menue, ab 150 % nicht mehr (bei 1280 und sieben Punkten lief
   sie mit Faktor 1,6 221px ueber den Rand). Deshalb misst
   navigation.js, ob sie wirklich passt, und setzt sonst `nav-eng` an
   <html> — dann bleibt es bei der Schublade. Wer die Schrift vergroessert,
   verliert so nichts, er bekommt nur das Menue, das auch schmale Fenster
   haben.

   Mit offenen Punkten ist die Mitte belegt, also steht das Lockup nicht
   mehr zentriert, sondern ganz links — eine Wortmarke
   steht ohnehin links, wo man sie liest. Der Hamburger faellt weg; die
   Rechtslinks auch (sie stehen im Fuss jeder Seite), im Quelltext bleiben
   beide. */
@media (min-width: 1024px) {
    :root:not(.nav-eng) .header-content,
    :root:not(.nav-eng) .lp-header {
        grid-template-columns: auto 1fr auto;
    }
    :root:not(.nav-eng) .header-content > .logo,
    :root:not(.nav-eng) .lp-header > .logo,
    :root:not(.nav-eng) .lp-header > a:not(.logo) {
        grid-column: 1;
        justify-self: start;
    }
    :root:not(.nav-eng) .header-controls { grid-column: 3; }
    /* Der Kopf der Rechtsseiten (und der KI-Demo) steht auf Lesebreite,
       760px — darin haben sieben Punkte neben Lockup und Knoepfen keinen
       Platz (gemessen: 43px ueber den Rand). Ab hier geht er ueber die
       volle Breite wie auf den Hauptseiten; der Text darunter bleibt
       schmal. header.lp-header, damit es auch das .wrap der KI-Demo
       schlaegt. */
    :root:not(.nav-eng) header.lp-header {
        max-width: none;
        padding-left: var(--gutter-text);
        padding-right: var(--gutter-text);
    }
    :root:not(.nav-eng) .header-links .nav-toggle { display: none; }
    /* Die Leiste steht seit dem 25.09.2026 im Quelltext direkt hinter dem
       Menueknopf, in .header-links (a11y-Rundgang): Unter 1024px kamen bei
       offener Schublade per Tab erst Chat-Knopf und Lockup, dann die
       Menuepunkte. Hier oben loest sich die Gruppe auf, damit die Leiste
       wieder ein Kind des Kopf-Rasters ist; Chat, Lockup und Knoepfe
       bekommen ihre Zelle fest zugewiesen. */
    :root:not(.nav-eng) .header-links { display: contents; }
    :root:not(.nav-eng) .header-content > .logo,
    :root:not(.nav-eng) .lp-header > .logo { grid-row: 1; }
    :root:not(.nav-eng) .header-controls { grid-row: 1; }

    :root:not(.nav-eng) .nav-links {
        /* grid-row fest: Im Quelltext steht die Leiste NACH den Knoepfen
           rechts, und die automatische Platzierung liefe sonst hinter
           Spalte 4 in eine zweite Zeile (gemessen: Kopf 137 statt 85px). */
        grid-column: 2;
        grid-row: 1;
        justify-self: end;
        position: static;
        width: auto;
        max-width: none;
        flex-direction: row;
        align-items: center;
        gap: 2px;
        padding: 0;
        background: none;
        border: 0;
        box-shadow: none;
        transform: none;
        visibility: visible;
        transition: none;
        overflow: visible;
    }
    :root:not(.nav-eng) .nav-links a {
        padding: 8px 10px;
        border-radius: 8px;
        font-size: 0.92rem;
        white-space: nowrap;
    }
    :root:not(.nav-eng) .nav-links .nav-legal,
    :root:not(.nav-eng) .nav-links .nav-divider { display: none; }
    :root:not(.nav-eng) .nav-links a[aria-current="page"] { color: var(--text); }
}

/* components/melucio-fab-stapel.css */
/*
 * Schwebende Knöpfe unten rechts: der Stapel (Frontend-Grundmuster Punkt 3 und 6)
 * David 17.10.2026: Chat-Knopf ganz unten, Nach-oben-Knopf darüber.
 *
 * Variablen (die Seite setzt sie in ihrer theme.css auf :root, die Fallbacks
 * gelten nur, wenn sie fehlen):
 *   --fab-rand   Abstand zur Fensterkante
 *   --fab-bot-h  Durchmesser des Chat-Knopfs (mindestens 44px Tap-Fläche)
 *   --fab-luft   Abstand zwischen den Knöpfen
 *   --fab-top-h  Durchmesser des Nach-oben-Knopfs (Vorgabe: wie --fab-bot-h)
 *
 * Markup, Inline-Variante (Astro-Buchsites):
 *   <a class="fab-stapel-chat" href="/gespraeche" aria-label="…">…</a>
 *   <button class="fab-stapel-top" id="scrollTop" aria-label="…">…</button>
 * Klassische Apps mit <melucio-scroll-top>: der Selektor unten hebt den
 * Baustein über den Chat-Knopf, sobald ein .fab-stapel-chat (oder
 * <khai-chat> o. ä. mit der Klasse) auf der Seite steht.
 *
 * Chat offen: das Skript des Chats setzt <html data-chat-offen>, dann ist
 * Nach-oben ausgeblendet. Ohne Chat-Knopf sitzt Nach-oben ganz unten.
 *
 * Einbinden: <link rel="stylesheet" href="/components/melucio-fab-stapel.css?v=202610201757">
 * (Cache-Buster, Grundmuster Punkt 7). Der Fuß weicht seitlich aus:
 * padding-inline: calc(var(--fab-rand) + var(--fab-bot-h)) (Punkt 6).
 */
.fab-stapel-chat,
.fab-stapel-top {
  position: fixed;
  box-sizing: border-box;
  right: var(--fab-rand, 1.1rem);
  display: grid;
  place-items: center;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  text-decoration: none;
}
.fab-stapel-chat {
  bottom: var(--fab-rand, 1.1rem);
  z-index: 48; /* unter Teilen-Sheet und Menüs (50), über Drawer (40) */
  width: var(--fab-bot-h, 2.8rem);
  height: var(--fab-bot-h, 2.8rem);
  min-width: 44px;
  min-height: 44px;
}
.fab-stapel-top {
  bottom: var(--fab-rand, 1.1rem);
  z-index: 47;
  width: var(--fab-top-h, var(--fab-bot-h, 2.8rem));
  height: var(--fab-top-h, var(--fab-bot-h, 2.8rem));
  min-width: 44px;
  min-height: 44px;
}
/* Mit Chat-Knopf rückt Nach-oben darüber. */
body:has(.fab-stapel-chat) .fab-stapel-top {
  bottom: calc(var(--fab-rand, 1.1rem) + max(var(--fab-bot-h, 2.8rem), 44px) + var(--fab-luft, 0.6rem));
}
body:has(.fab-stapel-chat) melucio-scroll-top {
  --scroll-top-bottom: calc(var(--fab-rand, 1.1rem) + max(var(--fab-bot-h, 2.8rem), 44px) + var(--fab-luft, 0.6rem));
  --scroll-top-right: calc(var(--fab-rand, 1.1rem) + (max(var(--fab-bot-h, 2.8rem), 44px) - 46px) / 2);
}
/* Chat offen: Nach-oben weicht, der Chat braucht den Platz. */
html[data-chat-offen] .fab-stapel-top,
html[data-chat-offen] melucio-scroll-top {
  display: none;
}
/* Unsichtbar heißt auch für die Tastatur weg (kein Fokus auf einem unsichtbaren Knopf). */
.fab-stapel-top:not(.is-visible) {
  visibility: hidden;
}

/* components/melucio-recht.css */
/* ══════════════════════════════════════════════════════════════════════
   Die Rechtsseiten: agb, datenschutz, impressum, widerruf, sicherheit
   ══════════════════════════════════════════════════════════════════════

   Bis zum 25.09.2026 trug jede der fuenf Seiten einen eigenen <style>-Block,
   fast wortgleich und trotzdem auseinandergelaufen (Stand-Zeile hiess
   einmal .lp-stand, einmal .lp-updated, im Impressum gab es keine). Jetzt
   steht alles hier, eingebunden nach melucio-nav.css mit ?v=202610201757.

   Vorgaben (design-berater, von David freigegeben am 25.09.2026):
   - Lesebreite 68ch, Fliesstext in --text statt --muted.
   - Abschnittsnummern in Markenlila (--brand-text, melucio-tokens.css).
     Gemessen im Browser auf dem Seitengrund: hell #6355D0 auf #f6f6fb
     und dunkel #A99EF8 auf #0a0a0f, Werte stehen unten bei .lp-nr.
   - Inhaltsverzeichnis immer offen, kein details/summary.
   - Fristen mit lila Unterstrich (seit 26.09.2026 einfarbig, siehe
     .lp-frist). Der Verlauf steht NIE hinter Schrift, nur als Kante.
   - Druckansicht ohne Kopf, Fuss und schwebende Knoepfe, schwarz auf weiss,
     Adressen der Links ausgeschrieben.
*/

:root {
    /* Masse der schwebenden Knoepfe (<melucio-scroll-top>: offset 20px,
       Knopf 46px), damit der Fuss ihnen seitlich ausweicht (Regel 6). */
    --fab-rand: 20px;
    --fab-bot-h: 46px;
    --lp-lesebreite: 68ch;
}

* { box-sizing: border-box; }
html { font-size: calc(16px * var(--font-scale, 1)); }
body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    /* Inter wie auf den Hauptseiten; @font-face steht in melucio-tokens.css.
       Bis zum 26.09.2026 lief der Fliesstext hier in der Systemschrift. */
    font-family: var(--body-font, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
    line-height: var(--read-lh, 1.65);
    letter-spacing: var(--read-ls, normal);
    -webkit-font-smoothing: antialiased;
}
a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Kopf ──────────────────────────────────────────────────────────────
   Aufteilung (drei Spalten, Lockup mittig), fester Kopf und --header-h
   kommen aus melucio-nav.css, damit Haupt- und Rechtsseiten denselben Kopf
   tragen. Hier bleiben Breite und Raender. */
.lp-header {
    max-width: 760px;
    margin: 0 auto;
    padding: 24px var(--gutter-text);
}

/* ── Inhalt ────────────────────────────────────────────────────────────
   Die Spalte bleibt 760px breit, damit Kopf, Text und Fuss an derselben
   linken Kante beginnen; die Zeilen selbst enden bei 68 Zeichen. */
.lp-main { max-width: 760px; margin: 0 auto; padding: 8px var(--gutter-text) 48px; }
.lp-main > *,
.lp-section > * { max-width: var(--lp-lesebreite); }
/* Die Schrift waechst mit der Breite so, dass das laengste Wort der
   Titel ("Geschaeftsbedingungen", in Bricolage 700 gemessen 11,42em breit)
   in eine Zeile passt: Spaltenbreite geteilt durch 11,8. Die Silbentrennung
   darunter greift in Chrome unter Windows nicht, ohne das brach das Wort bei
   320px als "Geschaeftsbedingunge / n". */
.lp-main h1 {
    color: var(--text);
    font-size: clamp(1.2rem, calc((100vw - 2 * var(--gutter-text)) / 11.8), 1.9rem);
    line-height: 1.25;
    margin: 0 0 6px;
}
/* Lange deutsche Einzelwoerter ("Geschaeftsbedingungen", "Datenschutzerklaerung")
   liefen bei 320px 15 bis 29px ueber den Rand (gemessen 25.09.2026, schon vor
   diesem Umbau). Trennen statt ueberlaufen; lang="de" liefert die Silben. */
/* Ueberschriften in Bricolage Grotesque wie auf der Startseite; Schrift und
   @font-face kommen aus melucio-tokens.css (--heading-font). */
.lp-main h1,
.lp-main h2 { font-family: var(--body-font, var(--heading-font)); }
.lp-main h1,
.lp-main h2 { hyphens: auto; -webkit-hyphens: auto; overflow-wrap: break-word; }

/* Eine Stand-Zeile fuer alle Seiten, ohne opacity: mit 0.8 lag sie im
   Dunkeln knapp an der Grenze, und sie ist eine Rechtsangabe. */
.lp-meta { font-size: 0.875rem; color: var(--muted); margin: 0 0 24px; }

.lp-intro { margin: 0 0 28px; }
.lp-section { margin: 0 0 32px; }
.lp-section h2 { color: var(--text); font-size: 1.12rem; line-height: 1.35; margin: 0 0 10px; }
.lp-section p { margin: 0 0 10px; }
.lp-section ul { margin: 0 0 10px; padding-left: 20px; }
.lp-section li { margin: 0 0 6px; }

/* Abschnittsnummer in Markenlila. Die Nummer bleibt Teil der Ueberschrift
   (vorgelesen wird "1. Geltungsbereich"), nur ihre Farbe ist eine andere.
   Gemessen 25.09.2026 im Browser (nach der Startseite in Logo-Lila, #1460):
   hell 5,21:1 auf dem Seitengrund und 5,61:1 auf der Karte des
   Verzeichnisses, dunkel 8,10:1 und 7,43:1, im hohen Kontrast hell 9,23:1,
   dunkel 10,31:1. */
.lp-nr {
    color: var(--brand-text);
    font-variant-numeric: tabular-nums;
}

/* ── Inhaltsverzeichnis ────────────────────────────────────────────────
   Immer offen: Wer eine Rechtsseite aufruft, sucht meist EINE Stelle,
   und ein geschlossener Aufklapper waere ein Klick mehr vor jedem Fund.
   Der lila Verlauf ist hier die linke Kante, nicht der Hintergrund. */
.lp-toc {
    position: relative;
    margin: 0 0 36px;
    padding: 14px 18px 14px 22px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
}
.lp-toc::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
    background: var(--gradient-1);
}
.lp-toc-titel {
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
    margin: 0 0 6px;
}
.lp-toc ol {
    list-style: none;
    margin: 0;
    padding: 0;
    columns: 2 16.5rem;
    column-gap: 24px;
}
.lp-toc li { break-inside: avoid; margin: 0; }
.lp-toc a {
    display: flex;
    align-items: center;
    gap: 0.35em;
    min-height: 32px;
    color: var(--text);
    line-height: 1.3;
}
.lp-main .lp-toc a { text-decoration: none; }   /* schlaegt die Unterstreichung aus melucio-tokens.css: im Verzeichnis ist jede Zeile ein Link */
.lp-main .lp-toc a:hover { color: var(--accent-text); text-decoration: underline; }
.lp-toc .lp-nr { min-width: 2.2em; }
/* Am Finger 44px je Eintrag, in px (CLAUDE.md, Tap-Flaechen). */
@media (pointer: coarse) {
    .lp-toc a { min-height: 44px; }
}

/* ── Auf einen Blick (nur AGB) ─────────────────────────────────────────
   Fasst nur zusammen, was in den Abschnitten steht, und verlinkt dorthin.
   Kante oben im lila Verlauf. */
.lp-blick {
    position: relative;
    margin: 0 0 28px;
    padding: 18px 20px 14px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
}
.lp-blick::before {
    content: '';
    position: absolute;
    left: 0; right: 0; top: 0;
    height: 4px;
    background: var(--gradient-1);
}
.lp-blick h2 { font-size: 1.12rem; margin: 0 0 10px; color: var(--text); }
.lp-blick dl { margin: 0; }
.lp-blick dl > div {
    padding: 10px 0;
    border-top: 1px solid var(--line-2, var(--border));
}
.lp-blick dl > div:first-child { border-top: 0; padding-top: 0; }
.lp-blick dt { font-weight: 700; color: var(--text); }
.lp-blick dd { margin: 2px 0 0; }
.lp-blick dd a {
    /* Eigene Zeile unter dem Satz: Inline mit 44px Hoehe riss sie am
       Telefon eine ungleich hohe letzte Zeile auf. */
    display: flex;
    width: fit-content;
    align-items: center;
    min-height: 32px;
    white-space: nowrap;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}
@media (pointer: coarse) {
    .lp-blick dd a { min-height: 44px; }
}
.lp-blick-hinweis { margin: 8px 0 0; font-size: 0.875rem; color: var(--muted); }
@media (min-width: 640px) {
    .lp-blick dl > div {
        display: grid;
        grid-template-columns: 9.5rem 1fr;
        gap: 16px;
    }
    .lp-blick dd { margin: 0; }
}

/* ── Fristen ───────────────────────────────────────────────────────────
   Lila Unterstrich, 3px, damit das Auge beim Ueberfliegen an den Zahlen
   haengen bleibt. Bis zum 26.09.2026 war das ein 3px-Streifen aus
   --gradient-1 als background-image. Die Kontrastmessung wertet ein
   Hintergrundbild aber als Flaeche HINTER der Schrift und kam so auf
   3,58:1 (hell, #15151f gegen #6a58e6), obwohl die Schrift auf dem
   Seitengrund steht. Eine Textunterstreichung ist ehrlicher: sie liegt
   sichtbar und messbar UNTER dem Text, bricht mit der Zeile um und braucht
   keinen Kniff. Farbe --accent-text (hell #5646C4, dunkel #A99EF8). */
.lp-frist {
    /* Halbfett und 3px, damit die Frist sich vom 1px-Unterstrich der Links
       abhebt und nicht wie einer aussieht. */
    font-weight: 600;
    text-decoration-line: underline;
    text-decoration-color: var(--accent-text);
    text-decoration-thickness: 3px;
    text-underline-offset: 4px;
    text-decoration-skip-ink: none;
}
/* Im hohen Kontrast in Schriftfarbe, wie die Verlaeufe dort auch. */
:root[data-contrast='high'] .lp-frist {
    text-decoration-color: currentColor;
}

/* ── Kontakt ───────────────────────────────────────────────────────────
   <address> statt Absatz: Die Anschrift ist als Kontaktangabe erkennbar.
   Links darin mit 44px Tap-Flaeche in px, nicht in rem. */
address { font-style: normal; }
.lp-kontakt { margin: 0 0 10px; }
address a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

/* ── Kaesten ───────────────────────────────────────────────────────── */
.kasten,
.lp-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 14px 18px;
    margin: 0 0 12px;
}
.kasten p,
.lp-card p { margin: 0 0 10px; }
.kasten p:last-child,
.lp-card p:last-child { margin-bottom: 0; }
.formular {
    background: var(--surface);
    border: 1px dashed var(--border);
    border-radius: 12px;
    padding: 16px 18px;
    margin: 0 0 12px;
}
.formular p { margin: 0 0 10px; }
/* Die Schreiblinie aus Unterstrichen ist ein einziges Wort und lief bei
   320px 31px ueber den Rand. Umbrechen darf sie ueberall. */
.formular p { overflow-wrap: anywhere; }
/* Abgesetzter Hinweis (Widerspruch nach Art. 21 Abs. 4: getrennt von
   anderen Informationen). */
.lp-box {
    margin: 14px 0 0;
    padding: 12px 16px;
    border: 1px solid var(--accent-line-strong);
    border-left-width: 4px;
    border-radius: 8px;
    background: var(--accent-fill-faint);
    color: var(--text);
}
.lp-box p:last-child { margin-bottom: 0; }

/* Widerruf- und Kuendigungsknopf (§ 356a, § 312k BGB). Traegt Text, bleibt
   deshalb eine Pille. */
.lp-knoepfe { display: flex; flex-wrap: wrap; gap: 12px; margin: 14px 0 6px; }
.lp-knopf {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 20px;
    border: 1.5px solid var(--accent);
    border-radius: 999px;
    color: var(--accent-text);
    font-weight: 600;
}
.lp-knopf:hover { text-decoration: none; background: var(--surface); }
/* Adresse im Fliesstext (Widerrufsfunktion im Muster-Satz): ein einziges
   langes Wort, darf bei 320px ueberall umbrechen. */
.lp-url { overflow-wrap: anywhere; }
/* Zusatzinformation ausserhalb eines gesetzlichen Musters (Widerruf:
   „Vorzeitiges Erloeschen"), sichtbar vom Muster abgesetzt. */
.lp-zusatz { border-top: 1px dashed var(--border); padding-top: 20px; }

/* Der Fuss steht seit dem 26.09.2026 in melucio-fuss.css, gemeinsam mit
   404, /ki-demo und /v/termin. */

:root[data-contrast='high'] .lp-card,
:root[data-contrast='high'] .lp-toc,
:root[data-contrast='high'] .lp-blick { border-color: var(--hc-line); }

/* ── Druck ─────────────────────────────────────────────────────────────
   AGB und Widerrufsbelehrung werden ausgedruckt und abgeheftet. Auf Papier
   zaehlt nur der Text: kein Kopf, kein Fuss, keine schwebenden Knoepfe,
   schwarz auf weiss, und jeder Link nennt seine Adresse, weil man auf
   Papier nicht klicken kann. */
@media print {
    @page { margin: 18mm 16mm; }
    body > :not(main) { display: none !important; }
    body {
        padding-top: 0 !important;
        background: #fff !important;
        color: #000 !important;
        font-size: 11pt;
        line-height: 1.45;
    }
    .lp-main { max-width: none; padding: 0; }
    .lp-main > *,
    .lp-section > * { max-width: none; }
    .lp-main *,
    .lp-main *::before,
    .lp-main *::after {
        color: #000 !important;
        background: none !important;
        box-shadow: none !important;
    }
    .lp-toc,
    .lp-blick,
    .kasten,
    .lp-card,
    .formular,
    .lp-box { border: 1px solid #000 !important; break-inside: avoid; }
    .lp-toc::before,
    .lp-blick::before { display: none; }
    .lp-toc ol { columns: 2; }
    .lp-toc a,
    .lp-blick dd a,
    address a { min-height: 0; display: inline; }
    .lp-section h2,
    .lp-blick h2 { break-after: avoid; }
    .lp-frist { text-decoration: underline; text-decoration-color: #000; text-decoration-thickness: 1.5px; text-underline-offset: 2px; padding: 0; }
    .lp-knopf { border: 0; padding: 0; min-height: 0; font-weight: 600; }
    .lp-knoepfe { display: block; }
    .lp-knoepfe .lp-knopf { display: block; }
    a { text-decoration: underline; }
    /* Adressen ausschreiben. Sprungmarken (#…) und mailto/tel nicht: deren
       Text IST schon die Angabe. */
    .lp-main a[href^="/"]::after { content: " (meluciolabs.de" attr(href) ")"; font-weight: 400; }
    .lp-main a[href^="http"]::after { content: " (" attr(href) ")"; font-weight: 400; word-break: break-all; }
}

/* components/melucio-fuss.css */
/* ══════════════════════════════════════════════════════════════════════
   Der statische Fuss: Rechtsseiten, 404, /ki-demo, /v/termin
   ══════════════════════════════════════════════════════════════════════

   Zwei <nav> mit Namen, "Seiten" und "Rechtliches", Widerruf und
   Kuendigung als Pillen, darunter das Copyright (26.09.2026, design-berater,
   von David freigegeben). Statisches HTML statt einer Komponente, weil die
   Seiten ohne Skript lesbar bleiben sollen und die Druckansicht den Fuss
   ohnehin weglaesst.

   SEIT 26.09.2026 AUF ALLEN SEITEN, auch den zwoelf Hauptseiten. Dort stand
   bis dahin <melucio-footer groups>, und die Links entstanden erst per
   Skript im Shadow-DOM: ohne JavaScript fehlten Impressum, Datenschutz,
   Kuendigung (§ 312k BGB) und Widerruf (§ 356a BGB) ganz
   (rechtstexte-pruefer 26.09.2026). Die Komponente leistete hier nichts,
   was dieser Fuss nicht auch kann; sie zu behalten und den Fuss als
   Rueckfall hineinzulegen haette dieselben Links zweimal gepflegt.
   Alle Seiten binden diese Datei im <head> ein, direkt nach melucio-nav.css.
   Die Gleichheit aller Fuesse prueft _tools/pruefe-kopf.mjs.

   Nichts davon steht in einem Modal: Impressum (§ 5 DDG), Kuendigung
   (§ 312k BGB), Widerruf (§ 356a BGB) und Datenschutz sind auf jeder
   Seite direkte Links.

   Stand vorher in drei Fassungen (melucio-recht.css, 404.html inline,
   Erzeuger von /v/termin inline), und /v/termin fehlte dabei der Link
   auf /barrierefreiheit (CLAUDE.md, Punkt 22). */

.lp-footer {
    max-width: 760px;
    width: 100%;
    margin: 0 auto;
    padding: 24px 0 40px;
    border-top: 1px solid var(--border);
    color: var(--muted);
    font-size: 0.875rem;
    text-align: center;
}
/* Auf den Hauptseiten laufen die Abschnitte ueber die ganze Breite; der
   Fuss tut es mit ihnen, wie vorher die Komponente (Linie vollbreit, Inhalt
   mittig). */
.lp-footer--seite { max-width: none; padding-top: 2rem; }
/* Nur der Copyright-Streifen weicht den schwebenden Knoepfen seitlich aus
   (CLAUDE.md, Punkt 6); die Linkzeilen bekommen 1rem, sonst bricht jede
   Zeile auf dem Telefon zweimal um. */
.lp-footer nav { padding-inline: 1rem; }
.lp-footer nav + nav::before {
    content: "";
    display: block;
    width: 40px;
    height: 1px;
    margin: 0.5rem auto;
    background: var(--border);
}
.fuss-zeile {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    column-gap: 4px;
}
.fuss-zeile + .fuss-zeile { margin-top: 0.25rem; }
.fuss-zeile > li { display: flex; align-items: center; }
.fuss-zeile a {
    padding: 2px 6px;
    color: var(--muted);
    text-decoration: none;
}
.fuss-zeile a:hover { color: var(--accent-text); text-decoration: none; }
.fuss-zeile.fuss-pillen { column-gap: 8px; row-gap: 8px; margin-top: 0.5rem; }
.fuss-zeile a,
.lp-footer a.fuss-pille { box-sizing: border-box; }
.lp-footer a.fuss-pille {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-height: 32px;
    padding: 0 12px;
    border: 1px solid var(--accent-text);
    border-radius: 999px;
    color: var(--accent-text);
    font-size: 0.8125rem;
    font-weight: 600;
    white-space: nowrap;
}
.lp-footer a.fuss-pille:hover { background: var(--accent-fill-faint); }
/* Die Pillen fuehren ins Portal und oeffnen dort einen neuen Tab, wie im
   Web-Component; das wird angesagt (WCAG 3.2.5), gleicher Wortlaut. */
.fuss-neu {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}
/* Mittelpunkte nur mit Maus und genug Breite; am Finger stuende nach jedem
   Umbruch ein verwaister Punkt am Zeilenanfang. Der Alternativtext "" haelt
   den Punkt aus der Vorlesung heraus. */
@media (pointer: fine) and (min-width: 768px) {
    .fuss-zeile:not(.fuss-pillen) > li + li::before {
        content: "\00B7";
        content: "\00B7" / "";
        margin: 0 0.35rem 0 0.1rem;
    }
}
/* Tap-Flaeche am Finger 44px, in px statt rem (CLAUDE.md, Punkt 7). */
@media (pointer: coarse) {
    .fuss-zeile a {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-height: 44px;
        min-width: 44px;
    }
    .lp-footer a.fuss-pille { min-height: 44px; }
    /* Die Tap-Flaechen sind schon 44px hoch, sie tragen den Abstand. */
    .fuss-zeile + .fuss-zeile:not(.fuss-pillen) { margin-top: 0; }
}
/* Unter 360px (iPhone SE, Galaxy S8) passte die Rechtszeile mit vier
   Links nicht mehr und brach in zwei. Etwas kleiner statt eine Zeile mehr. */
@media (max-width: 359px) {
    .lp-footer nav { padding-inline: 0.5rem; }
    .fuss-zeile a { padding-inline: 4px; font-size: 0.8125rem; }
}
.lp-footer .lp-copy {
    color: var(--muted);
    margin: 0.75rem 0 0;
    padding-inline: max(1rem, calc(var(--fab-rand, 20px) + var(--fab-bot-h, 46px)));
    font-size: 0.8rem;
}
.lp-footer .lp-copy a { color: var(--accent-text); text-decoration: underline; }
@media (max-width: 480px) {
    .lp-footer { padding-block: 1.5rem; }
}
:root[data-contrast='high'] .lp-footer,
:root[data-contrast='high'] .lp-footer nav + nav::before { border-color: var(--hc-line); }
:root[data-contrast='high'] .lp-footer nav + nav::before { background: var(--hc-line); }
