/* Lukas Springfeldt — Videograf, Portfolio.
   Umsetzung des Claude-Design-Entwurfs "Videograph Portfolio Webseite"
   (Datei "Lukas Springfeldt.dc.html"). Der Entwurf trug alle Werte inline
   im Markup; hier stehen sie einmal, damit eine Änderung am Aussehen eine
   Stelle hat. Die Zahlen sind unverändert übernommen.

   Die Seite ist ein Film: ein stehendes Bild (.stage), fünf Ebenen darin,
   und ein 820vh hoher Treiber (.driver), dessen Scrollstand die Ebenen
   blendet und bewegt. Alles Bewegte macht js/ls.js — das Stylesheet
   beschreibt nur den Ruhezustand. */

:root {
  --acc: #FF4A1C;        /* Akzent aus dem Entwurf (Prop accentColor) */
  --ink: #E8E6E1;        /* Schrift */
  --bg:  #050505;        /* Grund */
  --mid: #8b8b8b;        /* Beschriftung */
  --dim: #6b6b6b;        /* Beschriftung, leiser */
  --faint: #3d3d3d;      /* Platzhalterschrift auf den Platten */
}

* { box-sizing: border-box; }

html { background: var(--bg); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--acc); text-decoration: none; }
a:hover { color: var(--ink); }
::selection { background: var(--acc); color: var(--bg); }

.root { position: relative; background: var(--bg); }

/* Hinterlegte Ueberschriften. Der Akzent traegt die Schrift, statt sie nur
   einzufaerben — Kohle auf Signalorange haelt 6:1 und liest sich auch dort,
   wo hinter der Zeile eine Platte durchs Bild fliegt.
   `box-decoration-break: clone` gibt jeder Zeile ihren eigenen Kasten; ohne
   das liefe ueber den Umbruch ein einziger Block mit senkrechten Kanten.
   Die Polsterung steht in em, damit sie mit jeder Schriftgroesse mitwaechst —
   von der Metazeile bis zur Wortmarke ist derselbe Rand zu sehen. */
.hl {
  background: var(--acc);
  color: var(--bg);
  padding: 0 .09em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* ---------------------------------------------------------------- Bühne */

.stage {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: var(--bg);
  z-index: 0;
}

.layer { position: absolute; inset: 0; }

/* Die Streifenplatten stehen für Filmmaterial, das noch nicht da ist:
   ein 135°-Raster aus zwei fast gleichen Schwarztönen. Jede Platte trägt
   ihr eigenes Paar (--t1/--t2), damit die Stapel im Eintauchen nicht als
   eine Fläche verschmelzen. --s ist die Streifenbreite. */
.tex {
  --t1: #121212;
  --t2: #0a0a0a;
  --s: 10px;
  background: repeating-linear-gradient(135deg, var(--t1) 0 var(--s), var(--t2) var(--s) calc(var(--s) * 2));
}

/* --------------------------------------------------------- 01 TITEL */

.layer--title {
  display: flex;
  align-items: center;
  justify-content: center;
  will-change: opacity;
}

.title__plate {
  position: absolute;
  width: 58vw;
  aspect-ratio: 16 / 9;
  --t1: #101010;
  --t2: #0a0a0a;
  display: flex;
  align-items: center;
  justify-content: center;
  will-change: transform, opacity;
}

.title__slate {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.24em;
  color: var(--faint);
}

/* mix-blend-mode: difference — die Wortmarke kehrt sich um, wo die Platte
   hinter ihr hell wird. Das ist der Grund, warum der Titel beim Aufziehen
   der Platte lesbar bleibt, ohne einen Kasten zu brauchen. Der Titel ist die
   eine Ueberschrift, die bewusst NICHT hinterlegt ist: ein Block ueber beide
   Zeilen wuerde bei `line-height: .82` zu einer einzigen Flaeche verlaufen
   und das enge Stapeln der Wortmarke zerstoeren. */
.title__type {
  position: relative;
  text-align: center;
  will-change: transform, opacity;
  mix-blend-mode: difference;
}

.title__name {
  margin: 0;
  font-size: clamp(46px, 10.5vw, 190px);
  font-weight: 800;
  line-height: 0.82;
  letter-spacing: -0.045em;
  text-transform: uppercase;
}

.title__tags {
  margin-top: 26px;
  display: flex;
  gap: 22px;
  justify-content: center;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.26em;
  color: var(--mid);
}

/* ---------------------------------------------------- 02 EINTAUCHEN */

.layer--zoom {
  opacity: 0;
  pointer-events: none;
  perspective: 1200px;
}

.zplate {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 62vw;
  aspect-ratio: 16 / 9;
  margin: 0;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
  outline: 1px solid #1c1c1c;
}

.zplate:nth-of-type(1) { --t1: #121212; --t2: #0a0a0a; }
.zplate:nth-of-type(2) { --t1: #111111; --t2: #090909; }
.zplate:nth-of-type(3) { --t1: #131313; --t2: #0a0a0a; }
.zplate:nth-of-type(4) { --t1: #101010; --t2: #080808; }

/* Das Still fuellt die Platte randlos; die Streifenplatte darunter bleibt als
   Fallback, bis das Bild da ist. Ein Scrim am Fuss traegt Case und Metazeile —
   die Titel sind ohnehin hinterlegt (.hl) und brauchen ihn nicht. */
.zplate__img,
.ocard__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.zplate::after,
.ocard::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(5, 5, 5, 0) 48%, rgba(5, 5, 5, 0.82) 100%);
  pointer-events: none;
}

.zplate__body {
  position: absolute;
  z-index: 1;
  left: 0;
  bottom: 0;
  padding: 20px 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.zplate__case {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.26em;
  color: var(--acc);
}

.zplate__title {
  font-size: clamp(22px, 3vw, 44px);
  font-weight: 800;
  letter-spacing: -0.03em;
  text-transform: uppercase;
}

.zplate__meta {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.2em;
  color: #b4b4b4;
}

.zplate__still {
  position: absolute;
  z-index: 1;
  top: 16px;
  right: 20px;
  font-size: 10px;
  letter-spacing: 0.22em;
  color: rgba(255, 255, 255, 0.5);
}

/* Der Punkt in der Mitte ist der Fluchtpunkt: alle Platten wachsen aus ihm
   heraus auf den Betrachter zu. */
.zoom__dot {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 9px;
  height: 9px;
  margin: -4.5px 0 0 -4.5px;
  border-radius: 50%;
  background: var(--acc);
}

/* --------------------------------------------------------- 03 ORBIT */

.layer--orbit {
  opacity: 0;
  pointer-events: none;
  overflow: hidden;
  contain: paint;
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 1500px;
}

.ring {
  position: absolute;
  width: 1px;
  height: 1px;
  transform-style: preserve-3d;
  will-change: transform;
}

.ocard {
  position: absolute;
  /* Der Entwurf haelt Kartenbreite = 75 % des Bogenabstands zweier Nachbarn:
     bei sechs Karten (Radius 0.4 der Fensterbreite, 60 Grad Schritt) sind das
     genau die 30vw des Originals. Mit mehr Karten waere dieselbe Breite eine
     geschlossene Wand statt eines Rings — also folgt sie der Formel weiter:
     0.6 * sin(180/n); bei acht Karten 22.96vw. Aendert sich die Zahl der
     Produktionen, ist das die eine Stelle, die mitwandert (samt left/top als
     halbe Kantenlaengen und max-width im selben Verhaeltnis). */
  width: 22.96vw;
  max-width: 321px;
  aspect-ratio: 16 / 9;
  left: -11.48vw;
  top: -6.46vw;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  will-change: transform, opacity;
  outline: 1px solid #1b1b1b;
  --s: 8px;
  color: inherit;
  text-decoration: none;
  pointer-events: none;
}

/* Nur die vordere Karte ist anklickbar und fuehrt zum Film; die gedimmten
   Nachbarn fangen keine Klicks. Karten ohne Link (kein href) zeigen keinen
   Zeiger. */
.ocard.is-front[href] { pointer-events: auto; cursor: pointer; }

.ocard:nth-of-type(1) { --t1: #121212; --t2: #0a0a0a; }
.ocard:nth-of-type(2) { --t1: #111111; --t2: #090909; }
.ocard:nth-of-type(3) { --t1: #131313; --t2: #0b0b0b; }
.ocard:nth-of-type(4) { --t1: #101010; --t2: #080808; }
.ocard:nth-of-type(5) { --t1: #121212; --t2: #0a0a0a; }
.ocard:nth-of-type(6) { --t1: #111111; --t2: #090909; }
/* Die Werkschau traegt acht Produktionen, der Entwurf sah sechs Karten vor.
   Die zwei zusaetzlichen setzen die Folge der Schwarztoene fort. */
.ocard:nth-of-type(7) { --t1: #131313; --t2: #0b0b0b; }
.ocard:nth-of-type(8) { --t1: #101010; --t2: #080808; }

.ocard__label {
  position: absolute;
  z-index: 1;
  left: 16px;
  bottom: 14px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.24em;
  color: #c4c4c4;
}

/* Der Entwurf liess diesen Kasten ohne Breite: seine Kinder stehen alle
   absolut mit inset:0, also blieb er 0px breit. Der grosse Titel fiel das
   nicht auf — er ist eine Flexbox und laeuft symmetrisch ueber. Die Metazeile
   schon: sie brach an der laengsten Silbe in eine Spalte. Deshalb steht hier
   eine Breite. Am Titel aendert sie nichts, er bleibt auf der Mitte. */
.orbit__center {
  position: relative;
  width: 100%;
  padding: 0 4vw;
  text-align: center;
  pointer-events: none;
}

.orbit__titles { position: relative; height: clamp(52px, 7vw, 120px); }

.otitle {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(40px, 6.6vw, 118px);
  font-weight: 800;
  letter-spacing: -0.045em;
  text-transform: uppercase;
  will-change: opacity;
}

.otitle + .otitle { opacity: 0; }

.orbit__metas { position: relative; height: 20px; margin-top: 14px; }

.ometa {
  position: absolute;
  inset: 0;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.26em;
  color: #9a9a9a;
  will-change: opacity;
}

.ometa + .ometa { opacity: 0; }

/* -------------------------------------------------------- 04 PROFIL */

.layer--about {
  opacity: 0;
  pointer-events: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 6vw;
  padding: 0 8vw;
}

.about__col { display: flex; flex-direction: column; gap: 34px; }

.about__kicker {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.28em;
  color: var(--acc);
  will-change: transform, opacity;
}

.about__claim {
  font-size: clamp(26px, 3.4vw, 58px);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: pretty;
  will-change: transform, opacity;
}

.about__facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 26px 40px;
  max-width: 520px;
  will-change: transform, opacity;
}

.fact { display: flex; flex-direction: column; gap: 7px; }
.fact__key { font-size: 10px; letter-spacing: 0.24em; color: var(--dim); }
.fact__val { font-size: 19px; font-weight: 600; letter-spacing: -0.01em; }

.about__portrait {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 5;
  max-height: 70vh;
  justify-self: end;
  outline: 1px solid #1b1b1b;
  will-change: transform, opacity;
}

.about__portrait span {
  position: absolute;
  left: 18px;
  bottom: 16px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.24em;
  color: var(--faint);
}

/* ------------------------------------------------------- 05 KONTAKT */

.layer--contact {
  opacity: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 30px;
}

.contact__type {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 26px;
  will-change: transform, opacity;
}

.contact__sig { display: flex; flex-direction: column; align-items: center; gap: 18px; }

.contact__word {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.34em;
  line-height: 1;
  color: var(--ink);
}

.contact__avail {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.3em;
  color: var(--dim);
}

.contact__mail {
  font-size: clamp(28px, 5.6vw, 104px);
  font-weight: 800;
  letter-spacing: -0.04em;
  color: var(--ink);
}
/* Die Adresse traegt den Akzent schon als Flaeche, ein orangefarbener Hover
   waere unsichtbar. Beim Ueberfahren kippt der Block deshalb auf Knochenweiss. */
.contact__mail:hover .hl { background: var(--ink); }

.contact__rule { height: 2px; width: 0; background: var(--acc); }

.contact__links {
  display: flex;
  gap: 30px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.24em;
  color: var(--mid);
}
.contact__links a { color: var(--mid); }
.contact__links a:hover { color: var(--ink); }

/* Signet — der Winkel aus Balken mit dem S darin. Der Entwurf setzt ihn
   zweimal, im HUD und im Kontakt, im Verhältnis 1:4. Deshalb steht er
   hier einmal mit dem Faktor --k. */
/* Das Signet ist das LS-Monogramm im Rahmen (logo.svg, 44.39 x 108.4),
   inline im Markup, damit es die Tintenfarbe traegt. --k skaliert wie zuvor:
   k = 1 sind 24px Hoehe in der Kopfzeile, k = 4 der Kontakt. */
.lsmark {
  display: block;
  height: calc(24px * var(--k));
  width: auto;
  fill: var(--ink);
}

/* ------------------------------------------------- Schleier und Korn */

.vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 50%, rgba(0, 0, 0, 0) 42%, rgba(0, 0, 0, 0.72) 100%);
}

.grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.05;
  background-image: radial-gradient(#ffffff 0.5px, transparent 0.6px);
  background-size: 3px 3px;
}

/* ----------------------------------------------------------- HUD */

.hud {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 26px 32px;
  z-index: 50;
  pointer-events: none;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.26em;
  color: var(--mid);
}

.hud__mark { display: flex; align-items: center; gap: 13px; }

.hud__word {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.26em;
  line-height: 1;
  color: var(--ink);
}

.hud__tc { display: flex; align-items: center; gap: 9px; }

.hud__rec { width: 7px; height: 7px; border-radius: 50%; background: var(--acc); }

/* ------------------------------------------------------ Zeitleiste */

.scrub {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  padding: 0 32px 22px;
  cursor: ew-resize;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}

.scrub__ticks {
  display: flex;
  justify-content: space-between;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.24em;
  color: #5f5f5f;
  margin-bottom: 11px;
}

.scrub__track { position: relative; height: 3px; background: #1a1a1a; }
.scrub__fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: var(--acc); }
.scrub__head { position: absolute; top: -5px; left: 0; width: 2px; height: 13px; background: var(--ink); }

.hint {
  position: fixed;
  left: 50%;
  bottom: 74px;
  transform: translateX(-50%);
  z-index: 55;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.3em;
  color: #5f5f5f;
  pointer-events: none;
}

/* Der Treiber ist die ganze Seitenhöhe. Er zeigt nichts; sein Scrollstand
   ist die Zeitachse des Films. 820vh = Prop scrollLength des Entwurfs. */
.driver { height: 820vh; }

/* ------------------------------------------------------- Umbrüche */

/* Der Entwurf kennt nur die große Bühne. Unter 860px fällt das Profil auf
   eine Spalte, sonst stünden Text und Portrait nebeneinander im Nichts. */
@media (max-width: 860px) {
  .layer--about {
    grid-template-columns: 1fr;
    align-content: center;
    gap: 22px;
    padding: 0 7vw;
  }
  .about__col { gap: 22px; }
  .about__facts { gap: 18px 30px; }
  .about__portrait { justify-self: stretch; max-height: 34vh; }
}

/* Unter 700px trägt die Kopfzeile die Kapitelmarke nicht mehr — sie steht
   ohnehin in der Zeitleiste am Fuß. */
@media (max-width: 700px) {
  .hud { padding: 16px 18px; }
  .hud__chapter { display: none; }
  .scrub { padding: 0 18px 18px; }
  .scrub__ticks { font-size: 8px; letter-spacing: 0.1em; }
  .contact__links { gap: 18px; flex-wrap: wrap; justify-content: center; }
  .hint { font-size: 9px; letter-spacing: 0.22em; bottom: 66px; }
}

/* Wer Bewegung abbestellt hat, bekommt keine Dauerbewegung: der REC-Punkt
   hört auf zu pulsen und die Bühne folgt dem Scrollen ohne Nachlauf.
   Der Film selbst bleibt — er läuft nicht von allein, sondern nur so weit,
   wie gescrollt wird. */
@media (prefers-reduced-motion: reduce) {
  .hud__rec { opacity: 1 !important; }
}
