/* =============================================================================
   style.css - Aufbau (Reihenfolge = Reihenfolge in dieser Datei)

     1. Tokens        gemeinsame Werte (Farben, Schrift, Bewegung, Breiten)
     2. Schrift       @font-face (Geist, lokal eingebunden)
     3. Basis         Reset, html/body, Bild-Schutz, Links, Safari-Zeiger
     4. Cursor        eigener Mauszeiger, Pfeil-Hinweis (nur mit Maus)
     5. Kopf/Fuß      Name oben links, Impressum/Datenschutz unten links
     6. Startseite    Projektraster (#canvas, .patch), Ladeanzeige (#loader)
     7. CV-Spalte     Lebenslauf (per Klick auf den Namen)
     8. Projektansicht Popup, Schließen-Kreuz, Medien, Text
     9. Rechtstexte   Impressum, Datenschutz
    10. Responsive    alle Breitenregeln gesammelt: 900px, 700px, 600px

   Breakpoints (Handy-Wert auch in script.js: MOBILE_MAX_PX):
     900px  Projektansicht stapelt (Titel, Bild, Text)
     700px  Handy: CV-Spalte füllt das Fenster, Raster fährt komplett heraus
     600px  kleinere Titelschrift, Schließen-Kreuz näher am Rand
   ============================================================================= */


/* ---------- 1. Tokens ---------- */

/* "Schwarz" ist überall 90% Schwarz (kein reines #000) - errechnet als
   90% Deckung auf weißem Grund: 255 * 0.1 = 25.5 ≈ #1a1a1a. Als Volltonfarbe
   statt rgba(0,0,0,.9) definiert, damit z.B. der Cursor auch über Fotos
   konstant aussieht statt durchzuscheinen. */
:root {
  --ink: #1a1a1a;
  --muted: rgba(0, 0, 0, 0.55); /* Nebentext; ca. 4,7:1 Kontrast auf Weiß (WCAG AA) */
  --font: 'Geist', -apple-system, 'Helvetica Neue', Arial, sans-serif;
  --ease: cubic-bezier(.4, 0, .2, 1);
  --panel-ms: 0.3s;                       /* Ein-/Ausfahren der CV-Spalte und des Rasters */
  --text-lh: 17px;                        /* Zeilenabstand aller Fließtexte */
  --cv-width: clamp(300px, 31vw, 440px);  /* breit genug für die längsten CV-Zeilen */
  --media-max-h: 62vh;                    /* max. Bildhöhe in der Projektansicht; script.js überschreibt sie mit einem festen Pixelwert (62% der Fensterhöhe, höchstens 760px) */
  --native-cursor: none;                  /* nativer Mauszeiger ist überall unsichtbar (siehe 3. und 4.) */
}


/* ---------- 2. Schrift ---------- */

/* Lokal eingebettet statt von Google Fonts nachgeladen - sonst wird bei
   jedem Seitenaufruf die Besucher-IP an Google übertragen (bekanntes
   Abmahnrisiko in Deutschland, LG München 2022). Geist steht unter der
   SIL Open Font License 1.1 (freie Schrift, auch kommerziell nutzbar), hier
   als eine Variable-Font-Datei für die Schnitte 400 bis 700. */
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/Geist-Variable.woff2') format('woff2-variations'),
       url('fonts/Geist-Variable.woff2') format('woff2');
}


/* ---------- 3. Basis ---------- */

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  background: #ffffff;
  color: var(--ink);
  font-family: var(--font);
  font-weight: 500;
  overflow-x: hidden;
  cursor: var(--native-cursor); /* wird vererbt; ersetzt durch #custom-cursor */
}

/* Links bekommen vom Browser sonst per User-Agent-Stylesheet einen
   Hand-Cursor, der die Vererbung überschreibt. */
a {
  cursor: var(--native-cursor);
}

/* Safari-Workaround (siehe "Safari-Workaround" in script.js): Safari/macOS setzt
   den Zeiger bei Inhaltsänderungen unter der ruhenden Maus auf den Standardpfeil
   zurück. script.js wechselt deshalb kurz zwischen diesen zwei gleichwertigen,
   beide unsichtbaren Werten (none / durchsichtiges 1-Pixel-Bild). */
html[data-cursor-alt] {
  --native-cursor: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7") 0 0, none;
}

/* Bilder/Videos lassen sich nicht markieren oder per Drag herausziehen -
   kein Kopierschutz im eigentlichen Sinn (jede Datei, die der Browser
   anzeigt, lässt sich technisch immer über die Entwicklertools holen),
   aber blockiert die gängigen Wege: Rechtsklick-"Bild speichern unter",
   Herausziehen per Drag, Markieren+Kopieren, iOS-Long-Press-Menü. */
img, video {
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}


/* ---------- 4. Cursor ---------- */

/* Eigener Cursor: weißer Punkt mit dunklem Rand (auch auf dunklen Flächen
   sichtbar). Über Links kleiner (Hover-Hinweis), beim Klick zieht er sich
   zusätzlich zusammen. Über einer Projekt-Kachel wird er zur Kapsel mit dem
   Projektnamen (#cursor-label), über Name und Fußzeile dockt er als Oval an.
   Im Bildbereich der Projektansicht übernehmen die "<"/">"-Pfeile (#nav-arrow).
   Größe und Position setzt script.js (Abschnitt "Eigener Cursor"). */
#custom-cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: transparent; /* Basis-Punkt nur als Ring - Füllung nur bei der Titel-Kapsel (.labeled) */
  border: 2px solid var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  white-space: nowrap;
  pointer-events: none;
  z-index: 1000;
  opacity: 0;
  /* Zentrierung bleibt konstant translate(-50%,-50%) - Größe läuft über
     width/height, nie über scale(), damit der 2px-Rand bei jeder Größe gleich
     dick bleibt. left/top OHNE Transition, damit die freie Mausbewegung 1:1
     verzögerungsfrei bleibt; die Andock-Animation hat ihre Transition in
     .docked. */
  transform: translate(-50%, -50%);
  transition:
    opacity 0.15s ease,
    width 0.22s var(--ease),
    height 0.22s var(--ease),
    background-color 0.15s ease;
}

#custom-cursor.visible {
  opacity: 1;
}

/* Angedockt an Name oder Fußzeilen-Link: Position bekommt eine Transition, das
   Andocken wirkt wie ein Heranschweben. Beim Verlassen springt der Punkt sofort
   zur Mausposition zurück. */
#custom-cursor.docked {
  transition:
    opacity 0.15s ease,
    width 0.22s var(--ease),
    height 0.22s var(--ease),
    left 0.2s var(--ease),
    top 0.2s var(--ease);
}

/* Kapsel-Zustand: weiße Füllung, Text soll die Form eng ausfüllen. */
#custom-cursor.labeled {
  background: #ffffff;
}

#cursor-label {
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.15s ease;
}

#custom-cursor.labeled #cursor-label {
  opacity: 1;
  transition: opacity 0.15s ease 0.08s;
}

#nav-arrow {
  position: fixed;
  transform: translate(-50%, -50%);
  font-size: 34px;
  font-weight: 700;
  color: rgba(0, 0, 0, 0.8);
  pointer-events: none;
  opacity: 0;
  z-index: 250;
  user-select: none;
}

/* Touch-Geräte haben keinen Mauszeiger: eigener Cursor und Pfeil-Hinweis
   entfallen, Bilder werden per Tippen (linke/rechte Hälfte) oder Wischen
   gewechselt. Steht nach den Regeln oben, damit es sie überschreibt. */
@media (hover: none) and (pointer: coarse) {
  #custom-cursor,
  #nav-arrow {
    display: none;
  }
}


/* ---------- 5. Kopf und Fuß ---------- */

#site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  align-items: baseline;
  padding: 20px 24px;
  background: transparent;
  pointer-events: none; /* Klicks gehen durch die leeren Bereiche der Leiste auf den Inhalt darunter */
}

#site-header .brand {
  pointer-events: auto;
  display: inline-block;
  padding: 8px 10px;
  margin: -8px 0 0 -10px; /* Klickfläche vergrößert, visuelle Position bleibt gleich */
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
}

#site-footer {
  position: fixed;
  bottom: 0;
  left: 0;
  z-index: 50;
  display: flex;
  padding: 10px 16px;
  background: transparent;
}

#site-footer a {
  display: inline-block;
  padding: 6px 8px;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
}


/* ---------- 6. Startseite (Projektraster) ---------- */

/* Die Kacheln legt script.js absolut positioniert hinein (layout()). */
#canvas {
  position: relative;
  width: 100%;
  min-height: 100vh;
  padding-top: 64px;
  transition: transform var(--panel-ms) var(--ease);
}

.patch {
  position: absolute;
  display: block;
  opacity: 0;                        /* blendet weich ein, sobald das Medium geladen ist */
  transition: opacity 0.5s ease;     /* (script.js setzt die Klasse .ready) */
}

.patch.ready {
  opacity: 1;
}

.patch img,
.patch video {
  display: block;
  width: 100%;
  height: auto;
}


/* Ladeanzeige: pulsierender Punkt mit Text, solange die Medien der Startseite
   laden (script.js, Abschnitt "Startseite"). Erscheint erst nach 0,4s, damit
   schnelle Ladevorgänge (Cache) sie gar nicht erst zeigen. Name oben und Fußzeile
   stehen ohne Skript sofort (reines HTML/CSS). */
#loader {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 24px 32px;
  background: rgba(255, 255, 255, 0.92);
  z-index: 30; /* über dem Raster, unter CV-Spalte (40), Kopf/Fuß (50) und Projektansicht (100) */
  opacity: 0;
  animation: loader-in 0.4s ease 0.4s forwards;
  transition: opacity 0.35s ease;
  pointer-events: none;
}

#loader[hidden] {
  display: none;
}

#loader.done {
  opacity: 0;
  animation: none;
}

.loader-dot {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--ink);
  animation: loader-pulse 1.1s ease-in-out infinite;
}

.loader-text {
  margin: 0;
  font-size: 13px;
  color: var(--muted);
}

@keyframes loader-in {
  to { opacity: 1; }
}

@keyframes loader-pulse {
  0%, 100% { transform: scale(0.55); }
  50% { transform: scale(1.4); }
}

@keyframes loader-fade {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 1; }
}

/* Wer Bewegung reduziert hat: der Punkt blinkt sanft statt zu wachsen */
@media (prefers-reduced-motion: reduce) {
  .loader-dot {
    animation: loader-fade 1.6s ease-in-out infinite;
  }
}


/* ---------- 7. CV-Spalte ---------- */

/* Klick auf den Namen: die Spalte gleitet links herein, das Raster rutscht als
   Ganzes (Anordnung unverändert) um --cv-width nach rechts. Auf dem Handy ist
   --cv-width = Fensterbreite, das Raster fährt dadurch komplett heraus. Solange
   die Spalte offen ist, sind die Kacheln inaktiv; ein Klick auf die freie
   Fläche schließt die Spalte (script.js, Abschnitt "CV-Spalte"). */
body.cv-open #canvas {
  transform: translateX(var(--cv-width));
}

body.cv-open #canvas .patch {
  pointer-events: none;
}

#view-cv {
  position: fixed;
  top: 48px; /* etwas höher als die Kopfzeilen-Höhe der Startseite (64px): Inhalt rückt näher an den Namen */
  left: 0;
  bottom: 40px; /* endet oberhalb der fixierten Fußzeile */
  width: var(--cv-width);
  overflow-y: auto;
  scrollbar-width: none; /* Scrollen bleibt möglich, die graue Leiste entfällt */
  overscroll-behavior: contain; /* Scrollen im CV zieht die Seite dahinter nicht mit */
  background: #ffffff; /* Deckfläche: das Raster liegt darunter und darf nicht durchscheinen */
  transform: translateX(-100%);
  transition: transform var(--panel-ms) var(--ease);
  z-index: 40; /* unter dem Projekt-Overlay (100), über der Startseite */
}

#view-cv::-webkit-scrollbar {
  display: none;
}

body.cv-open #view-cv {
  transform: translateX(0);
}

.cv-panel-inner {
  --cv-indent: 16px; /* Überschriften stehen links, alles darunter ist leicht eingerückt */
  padding: 8px 16px 24px 24px;
}

.cv-portrait {
  display: block;
  width: 75%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center bottom; /* freier Hintergrund über dem Kopf wird abgeschnitten */
  margin: 0 0 16px;
}

/* Zeile unter dem Foto: gleiche Schrift wie die Abschnittsüberschriften */
.cv-identity,
.cv-panel-inner h2 {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
}

.cv-identity {
  line-height: 1.5;
  text-wrap: balance;
  margin: 0 0 8px;
}

.cv-panel-inner h2 {
  margin: 0 0 14px;
}

.cv-contact {
  font-size: 12px;
  font-weight: 600;
  line-height: var(--text-lh);
  margin: 0 0 48px var(--cv-indent);
}

.cv-panel-inner section {
  margin: 0 0 48px;
}

.cv-panel-inner .cv-entry {
  font-size: 12px;
  font-weight: 600; /* Ort/Institution und Titel gleich stark, nur das Datum tritt zurück */
  line-height: var(--text-lh);
  text-wrap: balance; /* verhindert einzelne Wörter in der letzten Zeile (z.B. "Grimme") */
  margin: 0 0 14px var(--cv-indent);
}

.cv-panel-inner .cv-entry strong {
  font-weight: inherit; /* sonst springt "bolder" relativ zu 600 auf 900 */
}

.cv-panel-inner .cv-date {
  display: block;
  font-size: 11px;
  font-weight: 400;
  color: var(--muted);
  margin: 0 0 2px;
}

.cv-panel-inner .cv-list {
  list-style: none;
  margin: 0 0 0 var(--cv-indent);
  padding: 0;
  font-size: 12px;
  font-weight: 600; /* wie die Einträge darüber */
  line-height: var(--text-lh);
}

.cv-panel-inner .cv-list li {
  margin: 0 0 8px;
  text-wrap: balance;
}

.cv-panel-inner a {
  color: var(--ink);
  font-size: 12px;
}


/* ---------- 8. Projektansicht (Popup) ---------- */

#overlay {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #ffffff;
  z-index: 100;
  overflow-y: auto;
}

#overlay.open {
  display: block;
}

#popup {
  position: relative;
  max-width: 1200px; /* Textspalten brauchen ca. 700px für 6-8 Wörter pro Zeile */
  width: 100%;
  margin: 0 auto;
  padding: 0 0 8vh;
}

/* Schließen-Kreuz der Projektansicht (#close) und von Impressum/Datenschutz
   (#page-close): Impressum/Datenschutz werden wie eine Projektseite geführt -
   rein, lesen, Kreuz zum Zurückkommen. */
#close,
#page-close {
  position: fixed;
  top: 24px;
  right: 32px;
  font-size: 48px;
  font-weight: 700;
  line-height: 1;
  color: rgba(0, 0, 0, 0.85);
  z-index: 200;
  user-select: none;
}

#close:hover,
#page-close:hover {
  color: var(--ink);
}

#header {
  display: grid;
  grid-template-columns: minmax(200px, 300px) 1fr;
  gap: 6vw;
  align-items: start;
  padding: 12vh 44px 0;
}

#title-block {
  padding-top: 4px;
}

#context-col {
  width: 100%;
}

#media {
  position: relative;
  width: 100%;
  min-height: 30vh;
  display: flex;
  align-items: center; /* vertikal zentriert innerhalb der fixen, per JS gesetzten Höhe */
  justify-content: flex-start;
  transition: opacity 0.15s ease; /* Abdunkeln, solange das nächste Bild lädt (script.js, renderMedia) */
}

#media img,
#media video {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: var(--media-max-h);
  margin: 0;
}

#info {
  padding: 40px 0 48px;
}

#p-title {
  font-size: 32px;
  font-weight: 700;
  margin: 0 0 20px;
  letter-spacing: -0.01em;
  line-height: 1.15;
}

#p-location,
#p-type {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 5px;
  letter-spacing: 0.01em;
}

/* Projekttext in zwei Spalten mit je ca. 6-8 Wörtern pro Zeile. Schriftgröße
   und Spaltenabstand (25px) folgen der Datenschutz-Seite von kerez.ch; Stärke 500
   und Zeilenabstand 17px sind die eigene Wahl. Absätze sind durch eine Leerzeile
   getrennt (white-space: pre-line). Bei schmalem Platz fällt der Text von selbst
   auf eine Spalte zurück (ab ca. 505px Textbreite sind es zwei). */
#p-text {
  font-size: 14px;
  font-weight: 500;
  line-height: var(--text-lh);
  margin: 0;
  white-space: pre-line;
  columns: 2 240px;
  column-gap: 25px;
}

#p-credits {
  font-size: 12px;
  color: var(--muted);
  margin: 36px 0 0;
  line-height: var(--text-lh);
}


/* ---------- 9. Rechtstexte (Impressum, Datenschutz) ---------- */

.page-view {
  min-height: 100vh;
  padding: 96px 24px 80px;
}

.legal-page {
  max-width: 640px;
}

.legal-page h1 {
  font-size: 28px;
  font-weight: 700;
  margin: 0 0 8px;
  letter-spacing: -0.01em;
}

.legal-page .subtitle {
  font-size: 14px;
  color: var(--muted);
  margin: 0 0 48px;
}

.legal-page section {
  margin: 0 0 40px;
}

.legal-page h1 + section {
  margin-top: 40px; /* Datenschutz hat keinen Untertitel zwischen Titel und erstem Abschnitt */
}

.legal-page h2 {
  font-size: 15px;
  font-weight: 700;
  margin: 0 0 20px;
  letter-spacing: 0.01em;
}

.legal-page p {
  font-size: 14px;
  line-height: var(--text-lh);
  margin: 0 0 16px;
}

.legal-page a {
  color: var(--ink);
}

.legal-note {
  color: var(--muted);
  font-size: 13px;
}

/* Seiten ohne eigenen Cursor (404.html lädt script.js nicht): normaler Mauszeiger */
.plain-page,
.plain-page a {
  cursor: auto;
}


/* ---------- 10. Responsive ---------- */

/* Schmale Fenster: Titel oben, darunter das Bild, dann der Text (einspaltig,
   sobald der Platz für zwei Spalten fehlt). */
@media (max-width: 900px) {
  #header {
    grid-template-columns: 1fr;
    gap: 28px;
    padding: 12vh 24px 0;
  }
}

/* Handy: die CV-Spalte füllt das ganze Fenster. */
@media (max-width: 700px) {
  :root {
    --cv-width: 100vw;
  }
}

@media (max-width: 600px) {
  #p-title {
    font-size: 26px;
  }

  #close,
  #page-close {
    right: 20px;
  }
}
