/* ============================================================
   Self-hosted variable fonts (latin, woff2) — DSGVO + Performance
   ============================================================ */
@font-face {
  font-family: "Fraunces";
  src: url("/fonts/fraunces.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  font-optical-sizing: auto;
}
@font-face {
  font-family: "Archivo";
  src: url("/fonts/archivo.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/jetbrains-mono.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

/* ============================================================
   Design tokens — Light (warmes Papier; Akzente WCAG-AA-geprüft)
   ============================================================ */
:root {
  --bg: #f4efe6;
  --paper: #fdfbf6;
  --surface: #ffffff;
  --ink: #1b1a17;
  --muted: #6a6256;        /* 4.6:1 auf --bg */
  --line: #e3dacb;
  --code-bg: #efe6d4;      /* solide Code-Fläche */

  --strat: #99551a;   --strat-bg: #fbefdd;   /* abgedunkelt → ≥4.5:1 auf strat-bg + surface */
  --disc:  #1e6e5b;   --disc-bg:  #e4f0eb;
  --fund:  #3c4a6e;   --fund-bg:  #e7eaf2;

  --info:  #2f7fb0;
  --comm:  #855a0d;   /* abgedunkelt → ≥4.5:1 auf hellen Flächen */
  --trans: #9a3324;

  --accent: var(--disc);
  --shadow: 0 1px 0 rgba(27, 26, 23, 0.04), 0 14px 34px -22px rgba(27, 26, 23, 0.34);

  --serif: "Fraunces", Georgia, "Times New Roman", serif;
  --sans: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  /* Typo-Skala — FLUID (rem + vw): skaliert stufenlos mit der Viewport-Breite,
     rem-basiert für Browser-Zoom/Skalierung. Min = Mobile, Max ab ~1500px Viewport. */
  --text-meta: clamp(0.875rem, 0.83rem + 0.12vw, 0.95rem);    /* 14 → 15 */
  --text-body: clamp(1.125rem, 1rem + 0.33vw, 1.3125rem);     /* 18 → 21 */
  --text-lg:   clamp(1.25rem, 1.08rem + 0.45vw, 1.5rem);      /* 20 → 24 */
  --text-h4:   clamp(1.4rem, 1.2rem + 0.53vw, 1.7rem);        /* 22 → 27 */
  --text-h3:   clamp(1.6rem, 1.33rem + 0.71vw, 2rem);         /* 26 → 32 */
  --text-h2:   clamp(1.6rem, 1.58rem + 0.98vw, 2.5rem);       /* 26 → 40 (Telefon-Floor gesenkt) */
  --text-h1:   clamp(1.85rem, 1.48rem + 1.9vw, 3.25rem);      /* 30 → 52 (Telefon-Floor gesenkt) */
  --text-display: clamp(2rem, 1.55rem + 2.8vw, 4.2rem);       /* 32 → 67 (Telefon-Floor gesenkt) */
  /* Floor-Senkung NUR am unteren Ende: das vw-Glied + max sind unverändert → die Kurve
     trifft die alten Werte exakt bei ~600px wieder (≥600px / Tablet+Desktop = 0 Regression);
     erst darunter (Telefone) werden die Überschriften klein genug, um nicht zu überlaufen. */

  /* Spacing-Skala (8px-Raster, 4px-Halbschritt) */
  --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem;
  --space-6: 1.5rem;  --space-8: 2rem;   --space-12: 3rem;   --space-16: 4rem;  --space-24: 6rem;
  --section-gap: clamp(3.5rem, 7vw, 6rem);   /* 56–96px Sektions-Rhythmus */
  --measure: 54rem;   /* Lesespalten-Breite (Prosa-Cap + Grid-Spalte) ≈ 72 CPL */
  --rail-space: 1.75rem;   /* reservierter linker Korridor für die Lese-Schiene */

  color-scheme: light;
}

/* ============================================================
   Design tokens — Dark (warmes Dunkel; Kontrast komfortabel ~12–15:1, nicht maximiert)
   ============================================================ */
:root[data-theme="dark"] {
  --bg: #17140f;
  --paper: #211d16;
  --surface: #2a251c;
  --ink: #ece4d5;
  --muted: #a59c8c;        /* ≥4.5:1 auf --bg */
  --line: #393026;
  --code-bg: #2f2a20;

  --strat: #d6973f;   --strat-bg: #2a1f12;
  --disc:  #5cc1a3;   --disc-bg:  #122620;
  --fund:  #93a6d4;   --fund-bg:  #1a2030;

  --info:  #5aa9d4;
  --comm:  #d3a443;
  --trans: #df7565;

  --shadow: 0 1px 0 rgba(0, 0, 0, 0.25), 0 14px 34px -22px rgba(0, 0, 0, 0.7);

  color-scheme: dark;
}

/* ============================================================
   Tailwind theme mapping (inline → Utilities folgen dem Dark-Mode)
   ============================================================ */
/* (Tailwind @theme mapping entfernt — Bericht nutzt reine CSS-Tokens) */

/* ============================================================
   Base
   ============================================================ */
* { box-sizing: border-box; }

html { scroll-behavior: smooth; font-size: 100%; -webkit-text-size-adjust: 100%; }

/* Globales Sicherheitsnetz gegen horizontalen Überlauf. clip (NICHT hidden!) klemmt
   nur die X-Achse, erzeugt KEINEN Scroll-Container → bricht position:sticky (Topbar/
   Sidebar) nicht und lässt den persistierten View-Transition-Sidebar-Scroll unberührt;
   overflow-y bleibt visible. Die echten Ursachen sind an der Wurzel gefixt (Überschriften-
   Umbruch, Tabellen-Scroll-Wrapper, Code-/Glossar-Umbruch, Viz) — dies fängt nur
   Restkanten ab (z. B. den off-canvas Mobil-Drawer bei translateX(-100%)). :where()=Spez. 0. */
:where(html, body) { overflow-x: clip; }

body {
  margin: 0;
  background:
    radial-gradient(120% 80% at 80% -10%, color-mix(in oklab, var(--paper) 70%, #fff) 0%, transparent 55%),
    var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--text-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Überschriften: Typo-Skala + asymmetrische Margins (mehr Luft ÜBER der Überschrift) */
h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 600;
  color: var(--ink);
  text-wrap: balance;
  /* Lange deutsche Komposita (»Suchmaschinenoptimierung« = 23 Zeichen) müssen in
     schmalen Spalten brechen können — sonst sprengt die Überschrift den Viewport
     (Hero-Bug). WICHTIG: »anywhere« (nicht »break-word«), weil nur anywhere die
     MIN-CONTENT-Breite senkt → die min-content-bemessene Inhaltsspalte schrumpft mit
     auf den Viewport (break-word bricht zwar visuell, lässt die intrinsische Breite
     aber groß → die Spalte überläuft trotzdem). hyphens:auto liefert dabei saubere
     Silben-Trennstriche an bevorzugten Stellen (greift nur mit lang="de", ✓ BaseLayout);
     anywhere ist nur die Notbremse. Auf weiten Spalten bricht nichts → desktopneutral. */
  overflow-wrap: anywhere;
  hyphens: auto;
  -webkit-hyphens: auto;
}
h1 { font-size: var(--text-h1); line-height: 1.08; letter-spacing: -0.02em; margin: 0 0 0.5em; }
h2 { font-size: var(--text-h2); line-height: 1.15; letter-spacing: -0.01em; margin: 2.5em 0 0.5em; }
h3 { font-size: var(--text-h3); line-height: 1.2; margin: 2em 0 0.4em; }
h4 { font-size: var(--text-h4); line-height: 1.25; margin: 1.6em 0 0.4em; }

p { margin: 0 0 1em; }

a {
  color: var(--accent);
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
a:hover { text-decoration-thickness: 2px; }

code, kbd, samp { font-family: var(--mono); font-size: 0.9em; }

::selection { background: color-mix(in oklab, var(--disc) 25%, transparent); }

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--disc);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Eyebrow / Kicker — Kategorie-Label über Sektionen */
.eyebrow {
  font-family: var(--mono);
  font-size: var(--text-meta);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--muted);
  margin: 0 0 0.6rem;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--ink);
  color: var(--paper);
  padding: 10px 16px;
  border-radius: 0 0 8px 0;
  font-family: var(--mono);
  font-size: 0.8125rem;
}
.skip-link:focus { left: 0; }

/* Nur für Screenreader (visuell ausgeblendet, im A11y-Baum erhalten) */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

/* ============================================================
   View-Transition-Crossfade (Astro ClientRouter) — der weiche Seitenübergang.
   CSP-REIN: hier in global.css (style-src 'self'), KEIN Inline-<style>. Astro
   injiziert nur für transition:animate/transition:name einen Inline-<style>; wir
   nutzen ausschließlich transition:persist (reines Attribut) → kein Inline-Style.
   Nur Browser mit nativen View Transitions (Chromium, Safari ≥18.2) erzeugen die
   ::view-transition-Pseudos; sonst sofortiger Client-Swap (Übergang als Progressive
   Enhancement). Die persistierte Sidebar wird per JS gehalten (DOM+Scroll), nicht
   überblendet. WICHTIG: Die globale reduced-motion-Regel oben matcht die
   ::view-transition-*-Pseudos NICHT (eigener Pseudo-Element-Baum) → hier explizit.
   ============================================================ */
@keyframes vt-fade-out { to { opacity: 0; } }
@keyframes vt-fade-in  { from { opacity: 0; } }

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: vt-fade-out 180ms ease both; }
  ::view-transition-new(root) { animation: vt-fade-in 200ms ease both; }
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
}

/* ============================================================
   Prose — Lesetypografie (Layer-Cake: scannbare Subheads, ruhiger Rhythmus)
   ============================================================ */
.prose { font-size: var(--text-body); line-height: 1.7; }
.prose > * + * { margin-top: 1.15em; }
/* Maß für Fließtext (≈66 CPL); breite Visuals (SEO-Landkarte) dürfen ausbrechen */
/* Konsistente Lesespalte: ALLES im Lesefluss kappt auf dieselbe Breite (rem,
   damit auch große Überschriften gleich breit sind). Breite Visuals (Landkarte)
   bleiben Ausnahme. */
.prose > * { max-width: var(--measure); }
.prose > .landkarte { max-width: none; }
.prose :where(p, li) { hyphens: auto; }
.prose h2 { font-size: var(--text-h2); margin-top: 2.2em; margin-bottom: 0.5em; }
.prose h3 { font-size: var(--text-h3); margin-top: 1.8em; margin-bottom: 0.4em; }
.prose :where(h2, h3) { scroll-margin-top: 5rem; }
.prose ul, .prose ol { padding-left: 1.3em; }
.prose li + li { margin-top: 0.5em; }
.prose li { padding-left: 0.2em; }
.prose code:not(pre code) {
  background: color-mix(in oklab, var(--code-bg) 94%, var(--ink) 6%);
  color: var(--ink);
  padding: 0.1em 0.42em;
  border-radius: 5px;
  border: 1px solid color-mix(in oklab, var(--ink) 12%, transparent);
  /* Lange Tokens (googleusercontent.com, application/ld+json) dürfen umbrechen statt
     den Viewport zu sprengen — anywhere bricht notfalls an jeder Stelle und senkt die
     Min-Content-Breite (hilft auch Tabellenzellen beim Schrumpfen). Ersetzt das frühere
     white-space:nowrap, das schmale Telefone überlief. */
  overflow-wrap: anywhere;
}
/* Code-Chip in Überschriften: nur Headings MIT Code (:has) bekommen mehr Zeilenhöhe →
   genug Luft, falls ein langer Token-Chip jetzt über zwei Zeilen umbricht. */
.prose :is(h1, h2, h3, h4):has(code) {
  line-height: 1.35;
}
.prose pre {
  background: var(--code-bg);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 16px 18px;
  overflow-x: auto;
  font-size: 0.9rem;
  line-height: 1.55;
}
.prose blockquote {
  margin-inline: 0;
  padding: 0.4em 1.1em;
  border-left: 3px solid var(--disc);
  color: var(--muted);
  font-style: italic;
}
.prose hr { border: none; border-top: 1px solid var(--line); margin: 2.4em 0; }
/* Tabellen-Scroll-Wrapper: ein rehype-Plugin (Build-Zeit, astro.config.mjs) hüllt jede
   <table> in <figure class="table-scroll" role="region" tabindex="0" aria-label="…">.
   CSP-rein (nur Klassen/Attribute, kein Inline-Style), a11y-korrekt (scrollbare Region
   ist tastatur-fokussierbar, WCAG 2.1.1). overflow-x:auto fängt zu breite Tabellen ab:
   schmale Tabellen füllen die Spalte (table width:100%), nur strukturell breite
   überschreiten ihre Min-Content-Breite → scrollen kontrolliert IM Wrapper statt den
   Viewport zu sprengen. Der Wrapper selbst erbt max-width:var(--measure) von .prose > *. */
.prose .table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
.prose .table-scroll > table { margin: 0; }
.prose table { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
.prose th, .prose td { text-align: left; padding: 0.6em 0.7em; border-bottom: 1px solid var(--line); }
.prose th {
  font-family: var(--mono);
  font-size: var(--text-meta);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.prose strong { font-weight: 700; }

/* ============================================================
   Lese-Schiene — ruhige vertikale Fortschritts-Anzeige links der Prosa.
   Element-basiert (.reading-rail in .content, nur Lesemodus-Kapitel).
   NICHT mitscrollend: ein im Viewport fixierter Balken (sticky UNTER der
   Topbar) → er "taucht" nicht aus der Topbar auf, sondern steht stabil und
   füllt von oben nach unten mit (wie ein Ladebalken). Er sitzt im eigens
   reservierten linken Korridor (--rail-space) → der Mindest-Rand zur Nav
   bleibt erhalten, der Fließtext bleibt voll breit & bündig.
   • __bar  = Track (immer sichtbar, zarte Hairline), sticky im Viewport.
   • __fill = Akzent, wächst per CSS Scroll-driven Animation (KEIN JS, CSP-ok).
   Fallback (kein scroll()-Support / prefers-reduced-motion): nur Track.
   Dekorativ (aria-hidden; der Scrollbalken bleibt die echte Info). Mobil aus.
   ============================================================ */
.reading-rail {
  position: absolute;
  left: 0.95rem;   /* im Korridor näher am Text → Schiene bleibt am Standard-Rand zur Nav */
  top: 0;
  bottom: 0;
  width: 2px;
  pointer-events: none;
}
.reading-rail__bar {
  position: sticky;
  top: 5rem;
  display: block;
  height: calc(100vh - 8rem);
  height: calc(100dvh - 8rem);   /* iOS-Safari: dynamische Viewport-Höhe (Fallback: vh) */
  width: 2px;
  border-radius: 2px;
  overflow: hidden;
  background: color-mix(in oklab, var(--ink) 13%, transparent);
}
.reading-rail__fill {
  position: absolute;
  inset: 0;
  background: var(--disc);
  transform-origin: top;
  transform: scaleY(0);
  border-radius: 2px;
}
@keyframes reading-rail-fill {
  from { transform: scaleY(0); }
  to   { transform: scaleY(1); }
}
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .reading-rail__fill {
      animation: reading-rail-fill linear;
      animation-timeline: scroll(root block);
    }
  }
}
@media (max-width: 959px) {
  .reading-rail { display: none; }
}

/* ============================================================
   Print — sauberer Papier-/PDF-Ausdruck. Interaktive Chrome (Topbar, Sidebar,
   Seiten-TOC, Suche, Theme-Toggle, Lese-Schiene) raus; Prosa volle Breite; Viz,
   Tabellen, Code und Blockquotes seitenbruch-freundlich. Erzwingt die AA-geprüfte
   HELLE Palette unabhängig vom Theme (Dark-Mode würde sonst schwarze Flächen
   drucken). CSP-rein: lebt hier in global.css (style-src 'self'), kein Inline-Style.
   ============================================================ */
@media print {
  /* Helle, kontraststarke Palette erzwingen — überschreibt auch den Dark-Mode
     (gleiche Spezifität, später in der Quelle → gewinnt nur im print-Kontext). */
  :root,
  :root[data-theme="dark"] {
    --bg: #ffffff; --paper: #ffffff; --surface: #ffffff;
    --ink: #161310; --muted: #45413a; --line: #c7bfb0; --code-bg: #f1ece1;
    --strat: #7c4413; --strat-bg: #f7efe2;
    --disc:  #14564a; --disc-bg:  #e9f2ee;
    --fund:  #313d5c; --fund-bg:  #eceef5;
    --info:  #226a93; --comm: #6e4a0a; --trans: #8a2c1e;
    --shadow: none;
    color-scheme: light;
  }

  html { font-size: 92%; }
  body {
    background: #fff !important;
    color: var(--ink);
  }

  /* Semantische Farben/Karten der Visualisierungen, Callouts und Tabellen im
     Druck erhalten (Browser strippen sonst Hintergründe/Ränder). print-color-adjust
     vererbt → die Regel deckt auch verschachtelte Elemente (Viz-Innenleben,
     Tabellenzellen) ab. `.atag` (AgentTag) MUSS hier stehen: sein Ampel-Punkt
     codiert die Steuerbarkeits-Stufe über die FORM (gefüllt/halb/Ring = Füllung),
     die ohne erzwungenen Hintergrund-Druck zu identischen Ringen kollabieren würde. */
  figure, .callout, table, pre, blockquote, code,
  [class*="viz-"], .landkarte, .atag {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Solide CTA-Buttons (Home/404) sind Navigations-Chrome, kein Inhalt. Sie tragen
     weißen Text auf grüner Fläche; im Default-Druck (Hintergründe AUS) bliebe sonst
     unsichtbarer Weiß-auf-Weiß-Text. Im Druck darum als lesbare Outline (ink). */
  .btn {
    color: var(--ink) !important;
    background: transparent !important;
    border: 1px solid var(--ink) !important;
    box-shadow: none !important;
    filter: none !important;
  }

  /* Interaktive Navigations-Chrome ausblenden */
  .skip-link,
  .topbar,
  .sidebar,
  .nav-scrim,
  .nav-toggle,
  .toc,
  .toc__toggle,
  .search-trigger,
  .search-dialog,
  .theme-toggle,
  .reading-rail {
    display: none !important;
  }

  /* Layout auf eine volle Spalte zurücksetzen */
  .shell,
  .content-frame,
  .content-frame.reading,
  .content-frame.reading.has-toc {
    display: block !important;
    grid-template-columns: none !important;
    grid-template-areas: none !important;
    min-height: 0;
  }
  .content,
  .content-frame.reading .content {
    padding: 0 !important;
    max-width: none !important;
  }

  /* Prosa über die volle Seitenbreite (Lesespalten-Cap aufheben) */
  .prose > *,
  .prose > .landkarte { max-width: none !important; }

  /* Seitenränder + Seitenumbruch-Hygiene */
  @page { margin: 1.6cm; }
  h1, h2, h3, h4 { break-after: avoid; }
  p { orphans: 3; widows: 3; }
  figure, table, pre, blockquote, img { break-inside: avoid; }
  .prose pre { white-space: pre-wrap; word-wrap: break-word; }
  .prose table { font-size: 0.85rem; }
  /* Im Druck nichts klemmen: der Tabellen-Scroll-Wrapper gibt die volle Tabelle frei. */
  .prose .table-scroll { overflow: visible; }
  :where(html, body) { overflow-x: visible; }

  /* Akzent-Unterstreichung der Links im Druck dezent halten; externe Ziele als
     URL ausweisen (interne/relative und Anker bleiben unannotiert). */
  .prose a { color: var(--ink); text-decoration: underline; }
  .prose a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-family: var(--mono);
    font-size: 0.78em;
    color: var(--muted);
    word-break: break-all;
  }
}
