% ============================================
% STEP 02: STYLING MIT TAILWIND & URBANIST
% ============================================

\section{Styling mit Tailwind CSS und Urbanist-Schriftart}
\label{sec:step02}

In diesem Schritt gestalten wir unsere Portfolio-Seite mit Tailwind CSS, binden eine eigene Schriftart ein und erstellen einen benutzerdefinierten Scrollbalken. Jede Zeile Code wird ausführlich erklärt.

\subsection{Schriftart Urbanist installieren}

Urbanist ist eine moderne, serifenlose Schriftart von Google Fonts mit 18 verschiedene Schnitten (Thin bis Black, jeweils normal und italic). Wir verwenden fünf Grundschnitte.

\textbf{Schritt 1: Schriftart-Dateien ins Projekt kopieren}

\begin{lstlisting}[language=Bash, caption={Schriftart-Dateien ins Public-Verzeichnis kopieren}]
cd ~/projects/portfolio
cp -r Urbanist apps/web/public/Urbanist
\end{lstlisting}

\textbf{Warum \texttt{public/}?}
\begin{itemize}
    \item Alles im \texttt{public/}-Ordner wird von Vite unverändert übernommen
    \item Dateien sind unter \texttt{/Urbanist/static/...} im Browser erreichbar
    \item Kein Import nötig – direkter Pfad in CSS
\end{itemize}

\subsection{Index.css – Das Herzstück des Stylings}

Die Datei \texttt{apps/web/src/index.css} vereint Tailwind, Schriftarten und Custom-Styles. Hier jede Zeile im Detail erklärt.

\subsubsection{Tailwind Import}

\begin{lstlisting}[language=CSS, caption={Tailwind CSS importieren}]
@import "tailwindcss";
\end{lstlisting}

\textbf{Erklärung:}
\begin{itemize}
    \item \texttt{@import} – CSS-Regel zum Importieren anderer Stylesheets
    \item \texttt{"tailwindcss"} – Lädt alle Tailwind-Basis-Styles, Komponenten und Utilities
    \item In Tailwind 4 \textbf{kein} \texttt{@tailwind base/components/utilities} mehr!
    \item Diese einzige Zeile ersetzt Hunderte von handgeschriebenen CSS-Zeilen
\end{itemize}

\subsubsection{Schriftart-Definitionen (5 Schnitte)}

\begin{lstlisting}[language=CSS, caption={Urbanist Regular (400)}]
@font-face {
  font-family: "Urbanist";
  src: url("/Urbanist/static/Urbanist-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
\end{lstlisting}

\textbf{Zeile für Zeile:}
\begin{itemize}
    \item \texttt{@font-face} – CSS-At-Regel zum Definieren einer eigenen Schriftart
    \item \texttt{font-family: "Urbanist"} – Der Name, unter dem wir die Schrift später verwenden (z.B. in \texttt{font-family: var(--font-display)})
    \item \texttt{src: url("/Urbanist/...")} – Pfad zur Schriftdatei. Beginnt mit \texttt{/}, ist also relativ zur Domain-Root
    \item \texttt{format("truetype")} – Sagt dem Browser, welches Format die Datei hat (.ttf = TrueType)
    \item \texttt{font-weight: 400} – Diesen Schnitt für normale Textstärke verwenden (400 = Regular)
    \item \texttt{font-style: normal} – Kein Kursiv (italic wäre \texttt{font-style: italic})
    \item \texttt{font-display: swap} – WICHTIG! Zeigt sofort Text in einer Ersatzschrift an und tauscht sie aus, sobald Urbanist geladen ist. Verhindert "Flash of Invisible Text" (FOIT)
\end{itemize}

\textbf{Die 5 definierten Schnitte:}
\begin{enumerate}
    \item \texttt{Urbanist-Light.ttf} – Gewicht 300 (dünn, für Fließtext)
    \item \texttt{Urbanist-Regular.ttf} – Gewicht 400 (normal, Standard)
    \item \texttt{Urbanist-Medium.ttf} – Gewicht 500 (halbfett)
    \item \texttt{Urbanist-SemiBold.ttf} – Gewicht 600 (fast fett)
    \item \texttt{Urbanist-Bold.ttf} – Gewicht 700 (fett, für Überschriften)
\end{enumerate}

\subsubsection{Tailwind Theme}

\begin{lstlisting}[language=CSS, caption={Tailwind Custom Theme}]
@theme {
  --font-display: "Urbanist", sans-serif;
  --breakpoint-3xl: 1920px;
  --color-primary: #8dff69;
}
\end{lstlisting}

\textbf{Zeile für Zeile:}
\begin{itemize}
    \item \texttt{@theme} – Tailwind 4 Direktive zum Erweitern/Überschreiben des Standard-Themes
    \item \texttt{--font-display: "Urbanist", sans-serif} – Definiert eine neue Schrift-Klasse \texttt{font-display}. \texttt{sans-serif} ist der Fallback, falls Urbanist nicht lädt
    \item \texttt{--breakpoint-3xl: 1920px} – Neuer Breakpoint für sehr große Bildschirme. Nutzbar als \texttt{3xl:text-7xl}
    \item \texttt{--color-primary: \#8dff69} – Definiert eine neue Farbe \texttt{primary} (helles Grün). Nutzbar als \texttt{text-primary}, \texttt{bg-primary}, \texttt{border-primary}, etc.
\end{itemize}

\textbf{Verwendung der Custom-Properties in Tailwind:}
\begin{itemize}
    \item \texttt{font-display} in \texttt{font-family: var(--font-display)}
    \item \texttt{3xl} als Breakpoint: \texttt{3xl:grid-cols-4}
    \item \texttt{primary} als Farbe: \texttt{text-primary}, \texttt{bg-primary/50}, \texttt{border-primary}
\end{itemize}

\subsubsection{Base-Layer (globale Stile)}

\begin{lstlisting}[language=CSS, caption={Globale Stile}]
@layer base {
  html {
    font-family: var(--font-display);
    scroll-behavior: smooth;
  }

  body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    background-color: #000000;
    color: #ffffff;
    overflow-x: hidden;
  }
}
\end{lstlisting}

\textbf{Zeile für Zeile:}
\begin{itemize}
    \item \texttt{@layer base} – Tailwinds "base"-Layer. Styles hier haben niedrigste Spezifität und können von Utilities überschrieben werden
    \item \texttt{font-family: var(--font-display)} – Setzt Urbanist als Standardschrift für die gesamte Seite
    \item \texttt{scroll-behavior: smooth} – Sanftes Scrollen bei Ankerlinks (z.B. \texttt{\#projekte})
    \item \texttt{-webkit-font-smoothing: antialiased} – Glättet Schrift auf macOS/iOS (WebKit-Browser)
    \item \texttt{-moz-osx-font-smoothing: grayscale} – Gleiches für Firefox auf macOS
    \item \texttt{background-color: \#000000} – Schwarzer Hintergrund
    \item \texttt{color: \#ffffff} – Weiße Schrift als Standard
    \item \texttt{overflow-x: hidden} – Verhindert horizontales Scrollen (wichtig für Animationen, die über den Rand hinausgehen)
\end{itemize}

\subsubsection{Custom Scrollbar (WebKit)}

\begin{lstlisting}[language=CSS, caption={Scrollbar für Chrome, Edge, Safari}]
::-webkit-scrollbar {
  width: 16px;
}

::-webkit-scrollbar-track {
  background: #1a1a1a;
}

::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, #8dff69, #6fe047);
  border-radius: 8px;
}

::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(180deg, #a8ff8d, #5bc92e);
}
\end{lstlisting}

\textbf{Zeile für Zeile:}
\begin{itemize}
    \item \texttt{::-webkit-scrollbar} – Pseudo-Element für die gesamte Scrollbar (Breite, Hintergrund)
    \item \texttt{width: 16px} – Breite der Scrollbar. Größer = dickerer Balken
    \item \texttt{::-webkit-scrollbar-track} – Der "Hintergrund" der Scrollbar (die Schiene)
    \item \texttt{background: \#1a1a1a} – Dunkelgrauer Track (fast schwarz)
    \item \texttt{::-webkit-scrollbar-thumb} – Der bewegliche "Griff" der Scrollbar
    \item \texttt{linear-gradient(180deg, \#8dff69, \#6fe047)} – Farbverlauf von hellgrün (oben) nach dunkelgrün (unten). \texttt{180deg} = von oben nach unten
    \item \texttt{border-radius: 8px} – Abgerundete Ecken am Griff
    \item \texttt{::-webkit-scrollbar-thumb:hover} – Wenn die Maus über dem Griff ist
    \item \texttt{\#a8ff8d, \#5bc92e} – Hellere Grüntöne beim Hover für visuelles Feedback
\end{itemize}

\subsubsection{Firefox Scrollbar}

\begin{lstlisting}[language=CSS, caption={Scrollbar für Firefox}]
* {
  scrollbar-width: auto;
  scrollbar-color: #6fe047 #1a1a1a;
}
\end{lstlisting}

\textbf{Erklärung:}
\begin{itemize}
    \item Firefox unterstützt \texttt{::-webkit-scrollbar} \textbf{nicht}
    \item \texttt{scrollbar-width: auto} – Normale Breite (Alternative: \texttt{thin})
    \item \texttt{scrollbar-color: GRIFF SCHIENE} – Erste Farbe = Griff, zweite Farbe = Schiene
\end{itemize}

\subsubsection{Hilfsklasse: Scrollbar ausblenden}

\begin{lstlisting}[language=CSS, caption={Hilfsklasse für Karussells}]
.hide-scrollbar::-webkit-scrollbar {
  display: none;
}
\end{lstlisting}

Für horizontale Karussells – der Inhalt scrollt, aber die Scrollbar ist unsichtbar.

\subsection{App.tsx – Die React-Komponente erklärt}

\begin{lstlisting}[language=TypeScript, caption={Vollständige App.tsx mit Zeilen-Erklärung}]
function App() {
  return (
    // Äußerster Container
    // min-h-screen: mindestens Bildschirmhöhe (wichtig für zentrierte Inhalte)
    // bg-black: schwarzer Hintergrund
    // text-white: weiße Schrift als Basis
    // p-8: 32px Innenabstand auf allen Seiten
    <div className="min-h-screen bg-black text-white p-8">

      {/* Zentrierte Content-Box */}
      {/* text-center: zentriert Text und Inline-Elemente */}
      {/* max-w-2xl: maximale Breite 672px */}
      {/* mx-auto: automatischer horizontaler Margin = zentriert die Box */}
      {/* pt-20: 80px Abstand nach oben (Padding-Top) */}
      <div className="text-center max-w-2xl mx-auto pt-20">

        {/* Kategorie-Badge: Kleine Beschriftung ÜBER der Überschrift */}
        {/* text-primary: verwendet unsere Custom-Farbe #8dff69 */}
        {/* text-sm: kleinere Schriftgröße (14px) */}
        {/* font-medium: halbfette Schrift (Gewicht 500) */}
        {/* tracking-widest: sehr breite Buchstabenabstände */}
        {/* uppercase: GROSSBUCHSTABEN */}
        <span className="text-primary text-sm font-medium tracking-widest uppercase">
          Full-Stack Entwickler
        </span>

        {/* Hauptüberschrift: Dein Name */}
        {/* text-7xl: sehr große Schrift (72px) */}
        {/* font-bold: fette Schrift (Gewicht 700) */}
        {/* mt-4: 16px Abstand nach oben */}
        {/* mb-6: 24px Abstand nach unten */}
        {/* leading-tight: enger Zeilenabstand (1.25) */}
        <h1 className="text-7xl font-bold mt-4 mb-6 leading-tight">
          Robert Bretz
        </h1>

        {/* Beschreibungstext */}
        {/* text-xl: etwas größerer Text (20px) */}
        {/* text-gray-400: graue Schrift (gedämpfter als weiß) */}
        {/* max-w-lg: maximale Breite 512px (schmaler = besser lesbar) */}
        {/* leading-relaxed: lockerer Zeilenabstand (1.625) */}
        <p className="text-xl text-gray-400 max-w-lg mx-auto leading-relaxed">
          Ich baue moderne Webanwendungen mit React, .NET und Docker.
          Minimalistisch, schnell und zuverlässig.
        </p>

        {/* Button-Gruppe */}
        {/* mt-10: 40px Abstand nach oben */}
        {/* flex: Flexbox-Layout */}
        {/* gap-4: 16px Abstand zwischen den Buttons */}
        {/* justify-center: Buttons horizontal zentrieren */}
        <div className="mt-10 flex gap-4 justify-center">

          {/* Button "Projekte" */}
          {/* px-6: 24px horizontaler Innenabstand */}
          {/* py-3: 12px vertikaler Innenabstand */}
          {/* bg-primary: Hintergrund in Custom-Farbe #8dff69 */}
          {/* text-black: schwarze Schrift auf grünem Grund */}
          {/* font-semibold: halbfette Schrift (Gewicht 600) */}
          {/* rounded-full: komplett runde Ecken (Pillenform) */}
          {/* hover:opacity-80: beim Hover auf 80% Deckkraft */}
          {/* transition: sanfter Übergang */}
          <a href="#" className="px-6 py-3 bg-primary text-black font-semibold rounded-full hover:opacity-80 transition">
            Projekte
          </a>

          {/* Button "Kontakt" */}
          {/* border border-gray-700: dunkelgrauer Rahmen statt Hintergrund */}
          {/* text-gray-300: hellgraue Schrift */}
          {/* hover:border-primary: Rahmen wird grün beim Hover */}
          {/* hover:text-primary: Schrift wird grün beim Hover */}
          <a href="#" className="px-6 py-3 border border-gray-700 text-gray-300 font-semibold rounded-full hover:border-primary hover:text-primary transition">
            Kontakt
          </a>
        </div>
      </div>

      {/* SCROLL-TEST: Erzwingt Scrollen für den Custom Scrollbar */}
      {/* mt-20: 80px Abstand nach oben */}
      {/* space-y-8: 32px Abstand zwischen den Kind-Elementen */}
      {/* max-w-2xl: gleiche maximale Breite wie oben */}
      <div className="mt-20 space-y-8 max-w-2xl mx-auto">
        {/* JavaScript: Erstelle 5 Test-Blöcke */}
        {/* [...Array(5)]: Array mit 5 leeren Plätzen */}
        {/* .map((_, i): für jedes Element, _ = ignorierter Wert, i = Index (0-4) */}
        {[...Array(5)].map((_, i) => (
          <div
            key={i}
            className="h-64 bg-gray-900 rounded-xl flex items-center justify-center text-gray-500 text-2xl"
          >
            Sektion {i + 1}
          </div>
        ))}
      </div>
    </div>
  );
}

export default App;
\end{lstlisting}

\subsection{Verwendete Tailwind-Klassen – Cheat Sheet}

\begin{table}[h]
\centering
\caption{Alle verwendeten Tailwind-Klassen und ihre CSS-Entsprechung}
\begin{tabular}{@{}llp{5cm}@{}}
\toprule
\textbf{Klasse} & \textbf{CSS-Entsprechung} & \textbf{Erklärung} \\
\midrule
\texttt{min-h-screen} & \texttt{min-height: 100vh} & Mindestens Bildschirmhöhe \\
\texttt{bg-black} & \texttt{background: \#000} & Schwarzer Hintergrund \\
\texttt{text-white} & \texttt{color: \#fff} & Weiße Schrift \\
\texttt{p-8} & \texttt{padding: 2rem} & 32px Innenabstand \\
\texttt{text-center} & \texttt{text-align: center} & Text zentrieren \\
\texttt{max-w-2xl} & \texttt{max-width: 42rem} & Max 672px breit \\
\texttt{mx-auto} & \texttt{margin-left/right: auto} & Horizontal zentrieren \\
\texttt{pt-20} & \texttt{padding-top: 5rem} & 80px oben \\
\bottomrule
\end{tabular}
\end{table}

\subsection{Scrollbalken-Debugging}

\textbf{Problem: "Ich sehe den Scrollbalken nicht!"}

\textbf{Ursache:} Der Scrollbalken erscheint nur, wenn die Seite tatsächlich scrollbar ist. Bei kurzen Inhalten (nur Name + Buttons) passt alles auf eine Bildschirmseite – kein Scrollbalken nötig.

\textbf{Lösungen:}
\begin{enumerate}
    \item Browser-Fenster vertikal verkleinern
    \item Genug Test-Inhalt einfügen (5 große Divs wie im Code oben)
    \item Mit \texttt{overflow-y: scroll} einen permanenten Scrollbalken erzwingen
\end{enumerate}

\subsection{Zusammenfassung}

In diesem Schritt haben wir:
\begin{itemize}
    \item Die Schriftart Urbanist mit 5 Schnitten eingebunden
    \item Ein Tailwind Custom-Theme mit eigener Farbe und Breakpoint definiert
    \item Globale Stile im \texttt{@layer base} gesetzt
    \item Einen benutzerdefinierten Scrollbalken mit Farbverlauf erstellt
    \item Jede Zeile der \texttt{App.tsx} und \texttt{index.css} ausführlich dokumentiert
\end{itemize}
