/* ============================================================
   VCI Design — Base
   Reset, Schriftbindung, Grundtypografie, Fokus, Reduced Motion.
   Setzt tokens.css voraus.
   ============================================================ */

/* --- Schriften, self-hosted ---------------------------------
   Keine Third-Party-Requests. Eine Familie fuer die ganze Seite,
   als Variable Font mit der Achse wght 400 bis 900. Regular und
   Italic sind zwei getrennte Dateien, weil Playfair Display die
   Kursive als eigenen Schnitt mitbringt und nicht als Achse.

   Kein unicode-range mehr: den brauchte Geist, weil es in eine
   Latin- und eine Latin-Ext-Datei geteilt war. Playfair deckt je
   Schnitt mit einer Datei alles ab, was auf der Seite vorkommt,
   nachgeprueft gegen jedes tatsaechlich verwendete Zeichen.

   font-named-instance waere hier wirkungslos. Der Deskriptor aus
   CSS Fonts 4 wird von keinem verbreiteten Browser ausgewertet,
   und noetig ist er auch nicht: der Bereich 400 900 macht alle
   sechs benannten Instanzen ueber normales font-weight
   erreichbar, Regular bis Black.
   ------------------------------------------------------------ */
@font-face {
  font-family: "Playfair Display";
  src: url("../assets/fonts/playfair-display-variable.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Playfair Display";
  src: url("../assets/fonts/playfair-display-italic-variable.woff2") format("woff2");
  font-weight: 400 900;
  font-style: italic;
  font-display: swap;
}

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

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  /* Unterdrueckt das graublaue Antipp-Rechteck auf Touch-Geraeten.
     Der Fokus-Ring bleibt davon unberuehrt. */
  -webkit-tap-highlight-color: transparent;
  /* HIER STAND scroll-behavior: smooth. Bitte nicht zurueckholen.

     Die Eigenschaft am Scroll-Container ist mit ScrollTrigger
     unvertraeglich. ScrollTrigger setzt bei jedem Refresh intern
     den Scroll auf 0, misst die Positionen und stellt ihn wieder
     her. Mit smooth wird dieses Setzen animiert statt sofort
     ausgefuehrt, und gemessen wird deshalb gegen die alte
     Scrollposition. Nachgemessen: scrollTop = 0 setzen, danach
     steht scrollY unveraendert bei 1300 und erreicht erst nach
     einer halben Sekunde 19.

     Die Folge war ein kaputter Hero-Pin nach jedem Refresh im
     gescrollten Zustand, also bei Fenstergroessenwechsel, beim
     Umschalten in den Vollbildmodus und beim Oeffnen der
     Entwicklerwerkzeuge: Pin-Start und Pin-Ende rutschten um die
     Scrollposition ins Negative, die Flaeche pinnte nicht mehr
     und stand knapp 1160 Pixel zu tief. Genau der weisse Balken
     zwischen Kopfzeile und Hero.

     Aufgefallen ist es erst nach Schritt 11: normalizeScroll hatte
     hier zuvor scroll-behavior auf auto gesetzt und das smooth
     damit stillgelegt. Mit dem Entfernen von normalizeScroll wurde
     es wieder wirksam.

     Weiche Ankerspruenge gehoeren, falls sie einmal gewuenscht
     sind, in JavaScript an den Klick auf den Anker, nie als
     CSS-Eigenschaft an den Scroll-Container. */

  /* Verhindert, dass ein per Anker angesprungenes Element unter
     dem klebenden Header verschwindet. */
  scroll-padding-top: calc(var(--header-height) + var(--space-m));
}

body {
  min-height: 100svh;
  background-color: var(--color-bg);
  color: var(--color-fg);
  font-family: var(--font-text);
  font-size: var(--text-medium);
  font-weight: var(--weight-regular);
  line-height: var(--leading-text);
  letter-spacing: var(--tracking-text);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  cursor: pointer;
}

p,
h1,
h2,
h3,
h4 {
  overflow-wrap: break-word;
}

ul[class],
ol[class] {
  list-style: none;
  padding: 0;
}

/* --- Grundtypografie ----------------------------------------
   Pairing-Regel aus dem Planungsdokument: Heading-Stufe wird mit
   einer Text-Stufe 1–2 Schritte darunter kombiniert.
   ------------------------------------------------------------ */
h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  text-wrap: balance;
}

h1 {
  font-size: var(--text-display-medium);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
}

h2 { font-size: var(--text-heading-large); }
h3 { font-size: var(--text-heading-medium); }
h4 { font-size: var(--text-medium); }

p {
  text-wrap: pretty;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: color var(--duration-short) var(--ease-base),
              opacity var(--duration-short) var(--ease-base);
}

/* --- Fokus ---------------------------------------------------
   Der Ring nutzt --color-focus (5.07:1), nicht das reine Cyan:
   #00e5e8 erreicht auf Weiss nur 1.50:1 und verfehlt damit die
   geforderten 3:1 fuer nicht-textuelle Kontraste.
   ------------------------------------------------------------ */
:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
  border-radius: 2px;
}

:focus:not(:focus-visible) {
  outline: none;
}

/* --- Hilfsklassen -------------------------------------------- */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Markierung fuer offene Stellen im Inhalt. Eckige Klammern
   allein reichen nicht, wenn jemand die Seite nur ueberfliegt,
   deshalb zusaetzlich eine gepunktete Unterlinie.

   Steht hier und nicht in einer Sektionsdatei, weil die Klasse
   seitenuebergreifend gedacht ist. Heute traegt sie nur noch
   arbeiten.html, fuer den Stand im Projektkopf und die Notiz unter
   "Ergebnisse". Zuvor lag sie in ueber-uns.css und blieb auf
   arbeiten.html deshalb wirkungslos. */
.platzhalter {
  border-bottom: 1px dotted currentColor;
  /* Etwas Luft, damit die Linie nicht an der Grundlinie klebt. */
  padding-bottom: 0.15em;
}

/* Wort-Spans fuer den Split-Text-Reveal (Pattern 4), erzeugt von
   js/split-text.js. inline-block ist keine Kosmetik, sondern
   Voraussetzung: auf reine Inline-Elemente wirkt transform nicht.
   Ein eigener Startzustand ist hier nicht noetig, das fromTo von
   GSAP setzt ihn beim Anlegen selbst. */
.split-wort {
  display: inline-block;
}

/* Solange der Magnetic Button laeuft (Pattern 5), uebernimmt GSAP
   die Bewegung allein. Die CSS-Transition der Buttons wuerde jeden
   geschriebenen Wert ein zweites Mal ueber 0,25s einschwingen, der
   Button folgte traege und doppelt gedaempft.

   Die Klasse setzt js/magnetic.js nur im aktiven Kontext. Auf Touch
   und bei reduzierter Bewegung bleibt sie aus, dort ist das
   CSS-Hover samt Transition die Rueckfallebene. */
[data-magnetic].magnet-aktiv {
  transition: none;
}

/* Startzustand fuer VCI.reveal(). Ohne JS bleibt der Inhalt
   sichtbar, deshalb wird er erst per .js-reveal-Klasse am
   <html> versteckt, die motion.js selbst setzt. */
.js-reveal [data-reveal] {
  opacity: 0;
}

/* Bei data-reveal-stagger animiert motion.js die Kinder statt
   des Containers. Bliebe der Container versteckt, waeren die
   Kinder trotz fertiger Animation nie zu sehen. Also Container
   sichtbar lassen und stattdessen die Kinder verdecken. */
.js-reveal [data-reveal][data-reveal-stagger] {
  opacity: 1;
}

.js-reveal [data-reveal][data-reveal-stagger] > * {
  opacity: 0;
}

/* Gegenstueck zum Riegel in reveal(): dort werden Kinder mit
   data-split aus den Stagger-Zielen genommen, weil sie sich
   wortweise selbst einblenden. Ohne diese Regel bliebe der
   Container aber von der Zeile darueber auf opacity 0 stehen,
   und niemand setzt ihn je zurueck. Die Woerter darin erreichen
   dann zwar 1, liegen aber in einem transparenten Elternteil.

   Genau das war der Fall: die CTA-Ueberschrift war seit der
   Einfuehrung von Pattern 4 dauerhaft unsichtbar. */
.js-reveal [data-reveal][data-reveal-stagger] > [data-split] {
  opacity: 1;
}

/* --- Reduced Motion ------------------------------------------
   Globale Notbremse fuer alles, was nicht ueber GSAP laeuft.
   GSAP-Animationen werden zusaetzlich in js/motion.js ueber
   gsap.matchMedia() behandelt.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    /* Bleibt als Netz stehen, falls spaeter irgendwo doch ein
       smooth gesetzt wird. Am <html> steht seit dem Pin-Fehler
       ohnehin keines mehr. */
    scroll-behavior: auto !important;
  }

  .js-reveal [data-reveal],
  .js-reveal [data-reveal][data-reveal-stagger] > * {
    opacity: 1;
  }
}
