/* ==========================================================================
   NOSC – Landing Page
   Ein Bildschirm, eine Marke. Keine Abhängigkeiten, kein Build-Schritt.
   Schriften liegen lokal (fonts/) – keine Google-Fonts-CDN, keine externen
   Requests, damit die Seite ohne Cookie-/Consent-Thema auskommt.
   ========================================================================== */

/* --- Schrift: Poppins, selbst gehostet ---------------------------------- */

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/poppins-300-latin.woff2') 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;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/poppins-300-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, 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: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/poppins-400-latin.woff2') 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;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/poppins-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, 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: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/poppins-500-latin.woff2') 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;
}


/* --- Farben ------------------------------------------------------------- */

:root {
  /* Dunkel ist der Standardauftritt. */
  --bg:          #08090a;
  --bg-lift:     #0f1113;
  --fg:          #f4f5f6;
  --fg-soft:     #9aa0a8;
  --fg-faint:    #5b6069;
  --line:        rgba(255, 255, 255, .09);
  --line-strong: rgba(255, 255, 255, .16);
  /* Der Schein hinter der Marke ist im Dunkelmodus heller als der Grund,
     im Hellmodus ebenfalls – die Marke steht in beiden Fällen im Licht. */
  --glow:        rgba(255, 255, 255, .07);
  --core-glow:   rgba(255, 255, 255, .10);

  /* Breite der Bildmarke. Alles andere im Logo skaliert im Verhältnis dazu.
     Das min() sorgt dafür, dass die Marke auch auf die Fensterhöhe reagiert –
     sonst füllt sie im Querformat eines Handys den halben Bildschirm. Die
     beiden clamp-Grenzen fangen sehr kleine und sehr große Displays ab. */
  /* 24.08.2026 leicht vergroessert: Obergrenze 184 -> 208 px (+13 %), die
     Anteile 32vw/30vh -> 36vw/34vh.

     11.09.2026 noch einmal: Obergrenze 208 -> 260 px (+25 %), Anteile
     36vw/34vh -> 40vw/38vh. Grund: der Schriftzug unter der Marke ist weg,
     der Name steht jetzt in den Kaestchen - die Marke ist das einzige
     Bildelement der Startseite und darf den freien Platz nehmen. Nebenbei
     werden die vier Buchstaben groesser und damit besser lesbar.

     Die UNTERGRENZE bleibt bei 112 px. Mit 126 px scrollte die Startseite auf
     einem niedrigen Querformat (568 x 320) um 28 px - gemessen. Auf so einem
     Schirm bestimmt ohnehin die Hoehe die Groesse, nicht die Untergrenze;
     sie anzuheben bringt dort nichts und kostet den Halt. */
  --lockup: clamp(112px, min(40vw, 38vh), 260px);
  --ease:   cubic-bezier(.16, .84, .32, 1);

  /* Seitenrand. Steht als Variable, weil die Leiste oben rechts (.topbar)
     genau denselben Abstand braucht wie der Inhalt darunter. */
  --pad:    clamp(28px, 6vw, 64px);
}

@media (prefers-color-scheme: light) {
  :root {
    --bg:          #f2f3f5;
    --bg-lift:     #ffffff;
    --fg:          #0a0b0d;
    --fg-soft:     #5f656d;
    --fg-faint:    #8e949c;
    --line:        rgba(10, 11, 13, .10);
    --line-strong: rgba(10, 11, 13, .20);
    /* Heller Kern auf leicht grauem Grund – dieselbe Idee wie im Dunkelmodus. */
    --glow:        rgba(255, 255, 255, .95);
    --core-glow:   rgba(10, 11, 13, .13);
  }
}


/* --- Grundgerüst -------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Untergrenze 24 statt 32 px: auf einem 320 px hohen Querformat sind 32 px
     ein Zehntel der Bildhoehe, und mit dem groesseren Wort scrollte die
     Startseite dort um 7 px. Ueber ~343 px Hoehe greift ohnehin 7vh, dort
     aendert sich nichts. */
  gap: clamp(24px, 7vh, 72px);
  padding: var(--pad);
  /* Bezugsrahmen fuer .topbar. */
  position: relative;

  background: var(--bg);
  color: var(--fg);
  font-family: 'Poppins', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* 300 als Grundgewicht: der einzige sichtbare Text auf der leeren Seite ist
     die Fußzeile. So lädt der Browser genau eine Schriftdatei. */
  font-weight: 300;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Weicher Lichtschein hinter der Marke – gibt der leeren Fläche Tiefe,
   ohne dass ein Gestaltungselement dazukommt. */
.ambient {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(52vw 52vh at 50% 44%, var(--glow), transparent 72%);
}

/* Feines Rauschen darüber. Große weiche Verläufe zeigen auf 8-Bit-Displays
   sonst deutliche Stufen – das Korn bricht sie auf. Liegt als Daten-URI
   direkt im Stylesheet, also kein zusätzlicher Request. */
.ambient::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: .035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: light) {
  .ambient::after { opacity: .028; mix-blend-mode: multiply; }
}

/* Die Bühne nimmt den ganzen freien Platz und zentriert ihren Inhalt darin.
   Ohne Projekte steht die Marke damit mittig im Bild; kommen Projekte dazu,
   wächst der Block nach unten und die Marke rutscht von selbst höher. */
.stage {
  position: relative;
  z-index: 1;
  flex: 1;
  width: 100%;
  max-width: 660px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}


/* --- Bild- und Wortmarke ------------------------------------------------ */

.brand {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.mark {
  width: var(--lockup);
  height: auto;
  display: block;
  fill: var(--fg);
  /* Die viewBox umschliesst die Marke exakt. Beim Driften wandern die
     Quadrate darueber hinaus – ohne overflow:visible wuerden sie am Rand
     abgeschnitten. */
  overflow: visible;
  /* Der Abstand darunter galt dem Schriftzug. Seit 11.09.2026 steht der Name
     in den Kästchen, der Schriftzug ist weg — und damit auch der Abstand,
     sonst säße die Marke sichtbar zu hoch (der Block ist senkrecht zentriert).
     Kommt der Schriftzug zurück, gehört hier calc(var(--lockup) * .138) hin. */
  margin-bottom: 0;
}

/* Ganz leichter Schein am Kernquadrat – hebt es vom Hintergrund ab,
   ohne die Kanten weich aussehen zu lassen. */
.mark__core {
  filter: drop-shadow(0 calc(var(--lockup) * .03) calc(var(--lockup) * .1) var(--core-glow));
}

/* Die Regeln für den Schriftzug (.wordmark, .wordmark__art) sind am
   11.09.2026 entfallen: der Name steht jetzt in den Kästchen der Bildmarke,
   die Grafik darunter gibt es nicht mehr. Tote Regeln stehen zu lassen wäre
   eine zweite Wahrheit — wer den Schriftzug zurückholt, findet Markup und CSS
   in der Git-Geschichte und in `_schriftzug-alt.html`.
   Die <h1> der Startseite ist jetzt `.sr-only`; sie braucht keine eigene
   Schriftregel, weil sie nie sichtbar ist. */

/* Nur für Screenreader sichtbar. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.tagline {
  margin: calc(var(--lockup) * .16) 0 0;
  max-width: 34ch;
  text-align: center;
  font-size: .9375rem;
  font-weight: 300;
  color: var(--fg);
  letter-spacing: .01em;
}
.tagline[hidden] { display: none; }

/* Der Verweis auf die Projekte, direkt unter dem Schriftzug. Er ist der
   einzige Weg von der Startseite in den Inhalt und stand bis 24.08.2026 in
   der Fusszeile.

   Abstand wie bei der Tagline am Logo bemessen (Anteil von --lockup), damit
   er auf jeder Bildschirmgroesse denselben Abstand zur Marke haelt.
   Der Unterstrich ist von Anfang an da: auf dem Handy gibt es kein Hover,
   und ohne ihn waere nicht zu sehen, dass das Wort antippbar ist. */
.brand__link {
  position: relative;
  /* Am Logo bemessen, nicht in Pixeln: so bleibt der Abstand auf jeder
     Bildschirmgroesse im selben Verhaeltnis zur Marke.
     Werdegang: .20 (37 px) war dem Owner zu eng, .32 (67 px) noch immer -
     jetzt .50.

     Das min(..., 11vh) ist die Bremse: auf einem 320 px hohen Querformat waeren
     .50 der Logobreite 56 px, und der Block scrollte aus dem Bild. Dieselbe
     Idee wie beim --lockup selbst, der auch nach der Fensterhoehe begrenzt ist.

     ACHTUNG bei weiteren Aenderungen: der Block ist als Ganzes senkrecht
     zentriert. Waechst dieser Abstand um X, rutscht das Wort nur um X/2 nach
     unten - und die Marke um X/2 nach oben. */
  margin-top: min(calc(var(--lockup) * .50), 11vh);
  /* 24.08.2026: von .9375rem auf 1.25rem (+33 %). Das Logo wuchs im selben
     Zug nur um 13 % - das Wort sollte ausdruecklich staerker zulegen als die
     Marke, dabei aber deutlich kleiner bleiben als sie. */
  font-size: 1.25rem;
  font-weight: 300;
  letter-spacing: .04em;
  color: var(--fg);
  text-decoration: none;
  border-bottom: 1px solid var(--line-strong);
  padding-bottom: 2px;
  transition: border-color .2s ease;
}
.brand__link:hover,
.brand__link:focus-visible { border-bottom-color: var(--fg); }
.brand__link:focus-visible {
  outline: 1px solid var(--line-strong);
  outline-offset: 4px;
  border-radius: 2px;
}
/* Vergroessert NUR die Trefferflaeche, nicht das Wort: 63 x 26 px sind mit
   dem Daumen zu knapp. Wort und Unterstrich bleiben unveraendert. */
.brand__link::after {
  content: '';
  position: absolute;
  inset: -12px -10px;
}

.brand__link[hidden] { display: none; }


/* --- Projektliste ------------------------------------------------------
   Steht seit 24.08.2026 auf einer eigenen Seite (projekte.html) und nicht
   mehr unter der Marke auf der Startseite. Weggefallen sind damit der
   Wrapper .projects, seine Ueberschrift und body.has-projects - letzteres
   vergroesserte die Marke, wenn die Liste MIT auf der Startseite stand.
   Die Ueberschrift der Seite ist jetzt ein normales .doc__title. */

.projects__list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}

.projects__item { border-bottom: 1px solid var(--line); }

.projects__row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px 4px;
  color: inherit;
  text-decoration: none;
  transition: padding-inline-start .35s var(--ease), color .2s ease;
}

a.projects__row:hover,
a.projects__row:focus-visible {
  padding-inline-start: 12px;
}
a.projects__row:focus-visible {
  outline: 1px solid var(--line-strong);
  outline-offset: 4px;
  border-radius: 4px;
}

/* --- Projekt-Logo -------------------------------------------------------
   Quadratisch mit runden Ecken – dieselbe Formensprache wie die Bildmarke.
   Liegt für ein Projekt keine Logodatei vor, zeichnet die Seite ein
   Monogramm aus dem Anfangsbuchstaben. Der Platz bleibt dadurch immer
   gleich groß, egal ob schon ein Logo da ist oder nicht.               */

.projects__logo {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 10px;                 /* ~24 % wie bei der Bildmarke */
  object-fit: contain;
  background: var(--bg-lift);
  border: 1px solid var(--line);
}

/* Ein echtes Logo bekommt eine HELLE Platte, das Monogramm nicht.

   Grund, gemessen am Teenvia-Logo (09.10.2026): es ist durchsichtig und
   besteht aus zwei Violett-Toenen, #2c24b7 und #4b3eff. Gegen die dunkle
   Kachel kommt der dunklere auf **1,78 : 1** - er verschwindet praktisch.
   Gegen Hell sind es 10,28 : 1. Fremde Logos sind nun einmal fuer ihren
   eigenen Grund gezeichnet, nicht fuer unseren; die Platte ist dasselbe, was
   ein Telefon mit App-Symbolen macht.

   Fester Wert, keine Variable: --bg-lift kippt im hellen Modus auf Weiss, und
   ein Logo, das im dunklen Modus lesbar ist, soll es im hellen auch bleiben.
   Das Polster haelt das Bild von der abgerundeten Kante weg - 2 px, weil
   das Teenvia-Logo schon eigenen Rand mitbringt und mit mehr zu klein wirkt.
   Ganz ohne waere ein randvolles Logo an den runden Ecken angeschnitten. */
img.projects__logo {
  background: #f4f5f6;
  padding: 2px;
}

.projects__logo--mono {
  display: grid;
  place-items: center;
  font-size: .9375rem;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--fg-soft);
  user-select: none;
}

/* Name und Beschreibung teilen sich eine Grundlinie, das Logo steht daneben. */
.projects__text {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 16px;
}

/* 09.10.2026 (Owner): die Liste soll im selben ruhigen Register stehen wie
   die Verweise in der Fusszeile - nichts Gesperrtes, nichts in
   Grossbuchstaben. Der Name bleibt trotzdem groesser als die Beschreibung,
   sonst ist er kein Name mehr, sondern eine Zeile unter vielen.
   Vorher: 1.125rem / 500 / .005em. */
.projects__name {
  font-size: .9375rem;
  font-weight: 400;
  letter-spacing: .01em;
  /* Sorgt dafür, dass die Beschreibungen untereinander auf einer Kante
     stehen, solange die Namen kurz sind. Längere Namen dürfen darüber hinaus. */
  min-width: 8rem;
}

/* Deutlich kleiner als der Name – die Beschreibung ist eine Fussnote,
   kein zweiter Titel. Seit 09.10.2026 auch blasser (--fg-soft statt --fg):
   im ruhigen Register stuenden sonst Name und Beschreibung gleich laut. */
.projects__desc {
  flex: 1;
  min-width: 0;
  font-size: .8125rem;
  font-weight: 300;
  letter-spacing: .01em;
  line-height: 1.45;
  color: var(--fg-soft);
}

/* `.projects__status` ist am 09.10.2026 ersatzlos entfallen - erst war es
   eine gesperrte Plakette, dann ein schlichtes Wort, jetzt gar nichts mehr:
   was nicht live ist, steht nicht auf der Seite. Tote Regeln stehen zu
   lassen waere eine zweite Wahrheit; die alte Fassung liegt in der
   Git-Geschichte. */

/* Der kleine Pfeil erscheint nur bei verlinkten Projekten. */
.projects__arrow {
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  fill: none;
  stroke: var(--fg-faint);
  stroke-width: 1.5;
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}
a.projects__row:hover .projects__arrow,
a.projects__row:focus-visible .projects__arrow {
  opacity: 1;
  transform: translateX(0);
}

@media (max-width: 560px) {
  .projects__row { gap: 14px; padding: 18px 2px; }
  .projects__text { flex-wrap: wrap; gap: 4px 12px; }
  .projects__name { min-width: 0; }
  .projects__desc { flex-basis: 100%; }
  .projects__logo { width: 34px; height: 34px; border-radius: 9px; }
}


/* --- Footer ------------------------------------------------------------- */

.footer {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  /* Umbruch, seit Kontakt und Impressum dazugekommen sind: vier Elemente
     passen zwischen 481 und rund 560 px sonst nicht mehr nebeneinander. */
  flex-wrap: wrap;
  justify-content: center;
  gap: 18px;
  font-size: .75rem;
  font-weight: 300;
  letter-spacing: .04em;
  color: var(--fg-faint);
}

.footer__link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color .2s ease, border-color .2s ease;
}
.footer__link:hover,
.footer__link:focus-visible {
  color: var(--fg);
  border-bottom-color: var(--line-strong);
}
.footer__link[hidden] { display: none; }


/* --- Leiste oben --------------------------------------------------------
   Links der Zurueck-Pfeil (nur auf Unterseiten), rechts der Sprachumschalter.
   Der Umschalter stand bis 24.08.2026 in der Fusszeile, die mit Kontakt und
   Impressum zu voll wurde; der Pfeil ersetzt seit 24.08.2026 die frueheren
   "Zur Startseite"-Links am Fuss der Textseiten.

   Absolut, nicht fest (fixed): auf dem Impressum wird gescrollt, und eine
   mitfahrende Leiste laege staendig ueber dem Text. So scrollt sie weg. */

.topbar {
  position: absolute;
  top: var(--pad);
  left: var(--pad);
  right: var(--pad);
  z-index: 2;
  display: flex;
  align-items: center;
  /* Feste Hoehe = Hoehe des Pfeils. Ohne sie waere die Leiste auf der
     Startseite (kein Pfeil) niedriger, und der Sprachumschalter saesse dort
     vier Pixel hoeher als auf den Unterseiten. */
  min-height: 32px;
  /* Die Leiste ist volle Breite und liegt damit ueber dem oberen Rand des
     Inhalts. Ohne das hier finge sie Klicks ab, die dem Inhalt gelten. */
  pointer-events: none;
}
.topbar > * { pointer-events: auto; }

/* Haelt den Umschalter rechts, egal ob links ein Pfeil steht oder nicht. */
.topbar .lang { margin-left: auto; }


/* --- Zurueck-Pfeil ------------------------------------------------------
   Fuehrt in den Verlauf zurueck, nicht auf die Startseite - siehe app.js.
   Das href="/" im HTML ist die Rueckfallebene ohne JavaScript und fuer den
   Fall, dass es gar kein Vorher gibt. */

.backlink {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Etwas groesser als das Zeichen darin: die Flaeche zum Antippen soll auch
     mit dem Daumen zu treffen sein, das Zeichen selbst aber klein bleiben. */
  width: 32px;
  height: 32px;
  margin-left: -8px;          /* das Zeichen steht damit auf der Randlinie */
  border-radius: 3px;
  color: var(--fg-faint);
  transition: color .2s ease;
}
.backlink:hover { color: var(--fg); }
.backlink:focus-visible {
  outline: 1px solid var(--line-strong);
  outline-offset: 2px;
}

.backlink__icon {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}


/* --- Sprachumschalter ---------------------------------------------------
   Englisch ist die Hauptsprache, Deutsch steht gleichwertig daneben
   (oesterreichischer Sitz). Die aktive Sprache ist die hellere von beiden. */

.lang {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.lang__btn {
  appearance: none;
  background: none;
  border: 0;
  padding: 2px 1px;
  margin: 0;
  font: inherit;
  font-size: .75rem;
  letter-spacing: .08em;
  color: var(--fg-faint);
  cursor: pointer;
  border-bottom: 1px solid transparent;
  transition: color .2s ease, border-color .2s ease;
}

.lang__btn:hover { color: var(--fg-soft); }

.lang__btn[aria-pressed="true"] {
  color: var(--fg);
  border-bottom-color: var(--line-strong);
  cursor: default;
}

.lang__btn:focus-visible {
  outline: 1px solid var(--line-strong);
  outline-offset: 3px;
  border-radius: 2px;
}

.lang__sep {
  color: var(--fg-faint);
  opacity: .5;
  font-size: .75rem;
}


/* --- Textseiten (Impressum, Kontakt, 404) -------------------------------
   Die Startseite ist eine Flaeche mit einer Marke in der Mitte. Diese Seiten
   sind das Gegenteil: gelesen wird von oben nach unten, in ruhiger
   Zeilenbreite. Das Logo steht auf ihnen NICHT - es gehoert seit 24.08.2026
   allein auf die Startseite. Ihre Ueberschrift (.doc__title) ist deshalb das
   <h1> der Seite; vorher war es der Schriftzug. */

/* Oben angeschlagen statt mittig - fuer einen langen Text ist das richtig.
   Nur das Impressum braucht das; Kontakt und 404 sind kurz und stehen mittig.

   Das padding-top ist NICHT Geschmack: seit das Logo nur noch auf der
   Startseite steht, faengt der Text ganz oben an - auf gleicher Hoehe wie die
   Leiste mit Pfeil und Sprachumschalter. Auf schmalen Bildschirmen liefe die
   Ueberschrift sonst in den Pfeil. 32px ist die Hoehe der Leiste, der Rest ist
   Abstand. */
.stage--doc {
  justify-content: flex-start;
  padding-top: calc(32px + clamp(20px, 5vh, 56px));
}

.doc {
  width: 100%;
  /* Keine eigene Maximalbreite: die Zeilenlaenge bestimmt .stage mit 660 px,
     damit Text und Startseite dieselbe Spalte teilen. */
  text-align: left;
  font-size: .9375rem;
  /* Eine Farbe fuer allen Lesetext: dieselbe, die auch die E-Mail hat.
     Beschriftungen (dt), das Statuszeichen und die Bedienelemente bleiben
     bewusst blasser - sie sind Hinweis, nicht Inhalt. */
  color: var(--fg);
}

/* Die Kontaktseite hat nur drei Zeilen - links ausgerichtet saehe sie
   verloren aus. */
.doc--center { text-align: center; }

.doc__title {
  margin: 0 0 clamp(24px, 4vh, 36px);
  font-size: 1.0625rem;
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--fg);
}

.doc__heading {
  margin: clamp(28px, 4vh, 40px) 0 10px;
  /* 11.09.2026 (Owner): dieselbe Farbe wie die Beschriftungen links
     (var(--fg-faint)), also blasser als der Lesetext. Dafuer eine Spur
     groesser - 13 -> 14 px -, damit die Ueberschrift trotz gleicher Farbe
     noch als Ueberschrift zu erkennen ist. Gilt fuer Impressum UND
     Datenschutzerklaerung; beide nutzen diese eine Regel. */
  font-size: .875rem;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--fg-faint);
}

.doc__block { margin: 0 0 10px; }

/* Zweispaltig, solange Platz ist: die Bezeichnung links, der Wert rechts.
   Auf schmalen Bildschirmen (unten) stapeln sie sich.

   Die erste Spalte ist FEST, nicht nach Inhalt bemessen. Jede Liste ist ein
   eigenes Raster; mit `auto` sucht sich jede ihre eigene Breite, und die
   Wertspalten der drei Bloecke stehen dann treppenfoermig versetzt. Mit
   `minmax(11rem, auto)` war das im Impressum 176 / 176 / 332 px - der letzte
   Block riss die Spalte auf, weil "Anwendbare gewerberechtliche Vorschriften"
   allein 332 px misst.

   14.5rem fasst jede normale Beschriftung in einer Zeile (die laengste ist
   "Zustaendige Gewerbebehoerde" mit 218 px). Die eine ueberlange bricht auf
   zwei Zeilen um - genau so, wie sie auch in der Vorlage des Owners steht. */
.doc__list {
  display: grid;
  grid-template-columns: 14.5rem 1fr;
  gap: 6px 20px;
  margin: 0;
}
.doc__list dt { color: var(--fg-faint); }
.doc__list dd { margin: 0; }

/* Eine Beschriftung, die auch in der festen Spalte nicht auf eine Zeile passt,
   nimmt die volle Breite; ihr Wert stellt sich darunter.
   Betrifft genau eine Zeile: "Anwendbare gewerberechtliche Vorschriften" misst
   332 px und braeche in der 232-px-Spalte auf DREI kurze Zeilen um. So steht
   sie auf einer - und genauso steht sie auch in der Vorlage des Owners. */
.doc__list .doc__wide { grid-column: 1 / -1; }

/* Links tragen die Textfarbe und sind allein am Unterstrich zu erkennen.
   `inherit` ist Pflicht, nicht Schoenheit: laesst man die Farbe ganz weg,
   greift die Regel des Browsers fuer Links und faerbt sie blau (gemessen:
   rgb(0,0,238)). Vererbung allein schlaegt diese Regel nicht. */
.doc a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--line-strong);
  transition: color .2s ease, border-color .2s ease;
}
.doc a:hover,
.doc a:focus-visible { border-bottom-color: var(--fg); }

.doc__mail { margin: 0 0 clamp(28px, 5vh, 44px); }

.doc__maillink {
  font-size: 1.125rem;
}


/* --- Auftritt beim Laden ------------------------------------------------ */

@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@keyframes settle {
  from { opacity: 0; transform: scale(.9); }
  to   { opacity: 1; transform: none; }
}

.mark__core,
.mark__node,
.tagline,
.brand__link,
.doc,
.topbar,
.footer {
  opacity: 0;
  animation: rise .8s var(--ease) forwards;
}

.mark__core         { transform-origin: 53.6% 60%; animation: settle .8s var(--ease) forwards; }
.mark__node         { transform-box: fill-box; transform-origin: center; animation: settle .7s var(--ease) forwards; }
.mark__node--n      { animation-delay: .16s; }
.mark__node--e      { animation-delay: .26s; }
.mark__node--s      { animation-delay: .36s; }
.mark__node--w      { animation-delay: .46s; }
.tagline            { animation-delay: .58s; }
.brand__link        { animation-delay: .66s; }
.doc                { animation-delay: .58s; }
.topbar             { animation-delay: .86s; }
.footer             { animation-delay: .86s; }


/* --- Dauerbewegung ------------------------------------------------------
   Die Marke steht nie ganz still. Jedes Quadrat sitzt in einer eigenen
   Gruppe (.mark__drift), die langsam driftet – das Rechteck darin behaelt
   seinen Auftritt beim Laden, die beiden Bewegungen kommen sich also nicht
   in die Quere.

   Die Werte sind viewBox-Einheiten: die Marke ist 228.4 Einheiten breit,
   ein Ausschlag von 8 sind also gut 3,5 % der Breite. Das ergibt rund
   2 px/s bei normaler Anzeigegroesse – langsam genug, dass es ruhig wirkt,
   schnell genug, dass man die Bewegung tatsaechlich sieht.

   Der kleinste Abstand zwischen einem Satelliten und dem Kern betraegt
   19 Einheiten; die Ausschlaege bleiben darunter, damit nichts zusammen-
   stoesst. Alle Umlaufzeiten sind teilerfremd, damit sich das Gesamtbild
   nicht sichtbar wiederholt.                                            */

.mark__drift {
  transform-box: fill-box;
  transform-origin: center;
  will-change: transform;
}

@keyframes drift-n {
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(4.5px, -6.5px); }
  45%  { transform: translate(-3px, -8.5px); }
  70%  { transform: translate(-6px, 2.5px); }
  88%  { transform: translate(1.5px, 5px); }
  100% { transform: translate(0, 0); }
}
@keyframes drift-e {
  0%   { transform: translate(0, 0); }
  22%  { transform: translate(7px, 3px); }
  48%  { transform: translate(2.5px, 8px); }
  72%  { transform: translate(-2.5px, 4.5px); }
  90%  { transform: translate(-3px, -3.5px); }
  100% { transform: translate(0, 0); }
}
@keyframes drift-w {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(-6.5px, 4.5px); }
  50%  { transform: translate(-2px, -7px); }
  75%  { transform: translate(5px, -2px); }
  100% { transform: translate(0, 0); }
}
@keyframes drift-s {
  0%   { transform: translate(0, 0); }
  18%  { transform: translate(4px, 7px); }
  46%  { transform: translate(-2.5px, 5.5px); }
  74%  { transform: translate(-2.5px, -5.5px); }
  92%  { transform: translate(5.5px, -1.5px); }
  100% { transform: translate(0, 0); }
}

/* Der Kern bleibt an seinem Platz und atmet nur – er ist der Anker,
   an dem das Auge die Marke wiedererkennt. */
@keyframes breathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.035); }
}

.mark__drift--n    { animation: drift-n 11s ease-in-out infinite; }
.mark__drift--e    { animation: drift-e 13s ease-in-out infinite; }
.mark__drift--w    { animation: drift-w 17s ease-in-out infinite; }
.mark__drift--s    { animation: drift-s  9s ease-in-out infinite; }
.mark__drift--core { animation: breathe  7s ease-in-out infinite; }

/* Auch der Lichtschein hinter der Marke bewegt sich – sehr langsam,
   damit die leere Flaeche nie ganz tot wirkt. */
@keyframes glow-breathe {
  0%, 100% { opacity: .82; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.09); }
}
.ambient { animation: glow-breathe 19s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) {
  .mark__core, .mark__node, .tagline, .brand__link, .doc, .topbar, .footer {
    opacity: 1;
    animation: none;
  }
  .mark__drift, .ambient { animation: none; }
  .projects__row, .projects__arrow, .lang__btn { transition: none; }
}


/* --- Kleine Bildschirme ------------------------------------------------- */

@media (max-width: 480px) {
  .footer { flex-direction: column; gap: 8px; text-align: center; }
}

/* Die Bezeichnungen im Impressum sind lang ("Zustaendige Gewerbebehoerde").
   Unter 560 px bleibt neben ihnen zu wenig fuer den Wert - dann untereinander. */
@media (max-width: 560px) {
  .doc__list { grid-template-columns: 1fr; gap: 0; }
  .doc__list dt { margin-top: 12px; }
  .doc__list dt:first-child { margin-top: 0; }
}
