/* ==========================================================================
   JARII · Akt 1 (Hero, Über uns) · Agent B
   Gehört zu src/partials/hero.html, about.html und assets/js/intro.js.
   Nur Tokens aus tokens.css verwenden.

   Zwei Zustände:
   1. Grundzustand (ohne JavaScript, reduzierte Bewegung, GSAP fehlt):
      Hero als normale 100svh-Sektion, darunter „Über uns“ als normale
      Salbei-Sektion. Nichts ist versteckt, nichts hängt von Skripten ab.
   2. html.has-intro (setzt early.js vor dem ersten Rendern, wenn keine
      reduzierte Bewegung gewünscht ist; main.js/intro.js nehmen sie zurück,
      wenn GSAP oder intro.js fehlt): beide Sektionen werden gleich hoch
      (--intro-h) und liegen übereinander, jede mit einer Sticky-Bühne
      (Technik „Scrub mit Sticky statt Pin“, docs/21st-referenzen.md Muster 2:
      kein Pin-Spacer, weniger Ruckeln auf iOS und beim Drehen).
      Schichten von unten nach oben: navy (Hintergrund #hero) ·
      Salbei-Fläche (Bühne von #ueber-uns, z 1) · Logo, Slogan, Hinweis
      (Bühne von #hero, z 101, also auch über dem Mini-Header mit z 100,
      damit das fliegende Logo beim Einblenden des Headers obenauf bleibt).
   ========================================================================== */

/* Logo-Größe: Desktop min(56vmin, 420px), mobil min(60vw, 260px) */
.intro { --intro-logo: min(56vmin, 420px); }
@media (max-width: 767px) {
  .intro { --intro-logo: min(60vw, 260px); }
}

/* --- Grundzustand Hero --------------------------------------------------- */
.intro {
  position: relative;
}
.intro__stage {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding-block: var(--space-16);
}
.intro__logo {
  width: var(--intro-logo);
  height: var(--intro-logo);
}
/* Keine Schatten, keine Filter am Logo (Markenbuch S. 5) */
.intro__svg { width: 100%; height: 100%; }

.intro__slogan {
  position: absolute;
  left: var(--gutter);
  bottom: var(--space-8);
  max-width: 22ch;
  color: var(--on-navy);
}

/* Zentriert ohne transform: GSAP bewegt das Element per transform (y), ein
   translateX(-50%) würde dabei in Pixel umgerechnet und beim Drehen falsch. */
.intro__scroll {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--space-6);
  width: max-content;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-height: 44px;
  min-width: 44px;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  color: var(--on-navy);
  text-decoration: none;
}
.intro__scroll:hover { color: var(--on-navy-accent); }

/* Sanftes Wippen des Pfeils. Nur transform. base.css schaltet Animationen
   bei reduzierter Bewegung ab. */
.intro__arrow { animation: intro-wippen 1.8s var(--ease) infinite; }
@keyframes intro-wippen {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(5px); }
}

@media (min-width: 768px) {
  .intro__slogan { left: var(--space-16); bottom: var(--space-12); }
  .intro__scroll { bottom: var(--space-12); }
}

/* Mobil stehen Slogan und Hinweis übereinander statt nebeneinander: bei
   390 px würde der zweizeilige Slogan sonst in den mittigen Hinweis laufen. */
@media (max-width: 767px) {
  .intro__slogan {
    bottom: calc(var(--space-6) + 52px + var(--space-4));
    max-width: 20ch;
  }
  /* Grundzustand ohne Animation: Die Bottom-Bar ist hier sichtbar (ohne
     JavaScript immer, bei reduzierter Bewegung sofort). Beides darüber halten. */
  html:not(.has-intro) .intro__scroll {
    bottom: calc(var(--bar-h) + var(--space-4) + env(safe-area-inset-bottom));
  }
  html:not(.has-intro) .intro__slogan {
    bottom: calc(var(--bar-h) + var(--space-4) + 52px + var(--space-4) + env(safe-area-inset-bottom));
  }
}

/* --- Grundzustand Über uns -----------------------------------------------
   Agent W, 26.10.2026: neu nach docs/aenderungen-2026-10-26.md (Abschnitte 2
   und 3). Produktaussage zuerst und am größten (heading-1), darunter body-l,
   dann Gründer-Karten und „Warum JARII“. */
.about__panel {
  padding-block: clamp(48px, 8vw, 96px);
}
.about__inner {
  display: grid;
  gap: var(--space-8);
}
.about__lead {
  display: grid;
  gap: var(--space-4);
}
/* heading-1 als größte Schrift der Fläche. max-width in ch hält die Zeile
   lesbar und bricht auf breiten Schirmen in zwei ruhige Zeilen. */
.about__title { max-width: 24ch; color: var(--on-sage); }
/* Einziger violet-Akzent der Fläche. violet auf Salbei 4,0:1: zulässig nur
   für große Schrift (heading-1 ist 32 bis 44 px, fett), tokens.css. */
.about__title .accent {
  color: var(--violet);
  white-space: nowrap;   /* „K.-o.-Tropfen“ nie am Bindestrich trennen (gemessen: brach bei 1440 und 390 px als „K.-o.-“ / „Tropfen“) */
}
.about__intro { max-width: 52ch; }

.about__cols {
  display: grid;
  gap: var(--space-8);
}
.about__label {
  margin-bottom: var(--space-3);
  color: var(--on-sage);
}
.about__text { max-width: 60ch; }

/* Gründer-Karten: Kapsel-Fotorahmen links, daneben Name und Rolle, darunter
   bzw. daneben der Satz. Kartenfläche surface-raised (Markenbuch: Karten auf
   raised), Innenabstand space-4, zwischen Karten space-4 bis space-6. */
.founders {
  display: grid;
  gap: var(--space-4);
  list-style: none;
}
.founder {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "photo name"
    "photo role"
    "text  text";
  align-content: start;
  column-gap: var(--space-4);
  row-gap: var(--space-1);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background-color: var(--surface-raised);
  color: var(--ink);
}
.founder__photo { grid-area: photo; align-self: start; }
.founder__name {
  grid-area: name;
  align-self: end;
  font-family: var(--font-display);
  font-size: 1.25rem;
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.founder__role {
  grid-area: role;
  align-self: start;
  color: var(--ink-muted);          /* 7,6:1 auf raised */
}
.founder__text {
  grid-area: text;
  margin-top: var(--space-3);
  font-size: 1rem;
  line-height: 1.5;
}

/* Kapsel-Rahmen (Grundform der Marke): 3:4 wie die Fotos, voll gerundet.
   Ohne Foto ein Monogramm navy auf lilac (10,2:1), Plus Jakarta 800. */
.portrait {
  width: 56px;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-pill);
  overflow: hidden;
  background-color: var(--lilac);
}
.portrait__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.portrait__mono {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  color: var(--navy);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.125rem;
  letter-spacing: -0.02em;
  line-height: 1;
}

.about__foot {
  margin-top: var(--space-4);
}

/* Ruhiger Textlink statt Button: die Hauptaktion bleibt „Auf die Liste“.
   Farbe on-sage statt violet, weil violet auf Salbei nur 4,0:1 erreicht
   (unter 4,5:1 für normale Schriftgröße, tokens.css). */
.about__next {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  color: var(--on-sage);
  font-weight: 600;
  text-decoration: underline;
}

@media (min-width: 768px) {
  .about__inner { gap: var(--space-12); }
  .about__lead { gap: var(--space-6); }
  /* Ab Tablet: Foto neben dem ganzen Text, Satz direkt unter der Rolle */
  .founder {
    grid-template-areas:
      "photo name"
      "photo role"
      "photo text";
    padding: var(--space-4) var(--space-6) var(--space-4) var(--space-4);
  }
  .founder__text { margin-top: var(--space-2); }
  .portrait { width: 72px; }
  .portrait__mono { font-size: 1.375rem; }
}

/* Ab 1024 px: Team links (7/12), „Warum JARII“ rechts (5/12) */
@media (min-width: 1024px) {
  .about__cols {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--space-16);
  }
}

/* ==========================================================================
   Animierter Zustand (nur mit html.has-intro)
   ========================================================================== */
html.has-intro { --intro-h: 350vh; }
@media (max-width: 767px) {
  html.has-intro { --intro-h: 260vh; }
}

html.has-intro .intro {
  height: var(--intro-h);
}
html.has-intro .intro__stage {
  position: sticky;
  top: 0;
  z-index: 101;
  height: 100vh;
  height: 100svh;
  min-height: 0;
  padding: 0;
  overflow: hidden;
  /* Die Bühne liegt über der Salbei-Fläche: Klicks und Auswahl gehen durch,
     nur der Scroll-Hinweis bleibt bedienbar. */
  pointer-events: none;
}
html.has-intro .intro__scroll { pointer-events: auto; }
html.has-intro .intro__logo { will-change: transform; }

/* Übergabe ans Header-Logo: intro.js setzt intro-handoff, sobald der Header
   fertig eingefahren ist. Bis dahin zeigt nur das fliegende Logo das Zeichen,
   danach nur das echte. So gibt es keinen Moment mit zwei Logos und keinen
   Sprung (das Header-Logo fährt sonst mit dem Header von oben herein). */
html.has-intro .site-header__logo img { transition: none; }
html.has-intro:not(.intro-handoff) .site-header__logo img { opacity: 0; }
html.has-intro.intro-handoff .intro__logo { opacity: 0; }

/* Über uns liegt über dem Hero. Höhe ergibt sich aus Bühne + Abstandhalter:
   - Die Bühne (sticky, top 0) ist mindestens eine Bildschirmhöhe hoch und
     wächst mit dem Inhalt (Handy).
   - Der Abstandhalter ::after ist so hoch wie die Scroll-Strecke des Hero
     (--intro-h minus eine Bildschirmhöhe). So klebt die Bühne genau, solange
     die Fläche einfährt (p 0 bis 1), und scrollt danach normal weiter.
   Ist der Inhalt höher als der Bildschirm, steht sein oberer Teil während
   der Animation im Bild, der Rest folgt beim Weiterscrollen. Nichts ist
   abgeschnitten, nichts liegt dauerhaft unter Header oder Bottom-Bar.
   Agent W, 26.10.2026 (vorher feste Höhe 100svh mit overflow hidden: auf
   dem Handy fehlte unten Inhalt). */
html.has-intro .about {
  position: relative;
  margin-top: calc(-1 * var(--intro-h));
}
html.has-intro .about::after {
  content: "";
  display: block;
  height: calc(var(--intro-h) - 100vh);
  height: calc(var(--intro-h) - 100svh);
}
html.has-intro .about__stage {
  position: sticky;
  top: 0;
  z-index: 1;
  min-height: 100vh;
  min-height: 100svh;
  /* Schneidet die Fläche ab, solange sie links außerhalb steht (kein
     waagrechtes Scrollen). clip statt hidden: macht die Bühne nicht zum
     Scroll-Container. */
  overflow: hidden;
  overflow: clip;
}
/* Bis intro.js die Startlage gesetzt hat (Klasse intro-ready), ist die
   Fläche unsichtbar. Agent P, 26.10.2026: Beim ersten Besuch (mobil, CPU 4×,
   Fast 4G) zeigte die Bildfolge ~0,7 s lang die fertige Salbei-Fläche mit
   Text über dem Hero, bevor GSAP sie nach links schob. visibility statt
   transform: Ein CSS-transform würde GSAP als Pixelwert übernehmen (siehe
   unten). Läuft intro.js nicht, nimmt main.js has-intro nach load zurück, die
   Regel greift dann nicht mehr. */
html.has-intro:not(.intro-ready) .about__panel { visibility: hidden; }

html.has-intro .about__panel {
  min-height: 100vh;
  min-height: 100svh;
  /* Inhalt senkrecht mittig im freien Raum unter dem Header: die Headline
     landet so im oberen Drittel. „safe“: wird es zu eng, beginnt der Inhalt
     oben statt über den oberen Rand hinaus. */
  display: flex;
  flex-direction: column;
  justify-content: safe center;
  /* Oben Platz für Mini-Header und den Logo-Zielort oben rechts */
  padding-top: calc(var(--head-h) + var(--space-12));
  padding-bottom: var(--space-24);  /* unten mehr als oben: Mitte leicht über der Bildmitte */
  /* Startlage translateX(-100%) setzt intro.js (xPercent). Hier kein
     transform, sonst addiert GSAP den CSS-Wert als Pixel dazu und die
     Fläche käme nie ganz herein. */
  will-change: transform;
}

/* Mobil: Der Inhalt ist höher als eine Bildschirmhöhe und beginnt oben unter
   dem Header (siehe oben: danach normales Weiterscrollen). Unten so viel
   Platz, dass „Zum Halm“ über der Bottom-Bar steht. */
@media (max-width: 767px) {
  html.has-intro .about__panel {
    justify-content: flex-start;
    padding-top: calc(var(--head-h) + var(--space-6));
    padding-bottom: calc(var(--bar-h) + var(--space-12) + env(safe-area-inset-bottom));
  }
}

/* Handy, alle Zustände: heading-1 eine Stufe kleiner, damit die Aussage auf
   360 px in drei Zeilen passt. */
@media (max-width: 767px) {
  .about__title { font-size: 1.75rem; line-height: 1.05; }
  .about__inner { gap: var(--space-8); }
}

/* Niedrige Desktop-Fenster (z. B. 1280 × 720): oben und unten weniger Luft,
   engere Abstände, damit der ganze Inhalt in die Fläche passt. */
@media (max-height: 800px) and (min-width: 768px) {
  html.has-intro .about__panel {
    padding-top: calc(var(--head-h) + var(--space-6));
    padding-bottom: var(--space-8);
  }
  html.has-intro .about__inner { gap: var(--space-8); }
  html.has-intro .about__lead { gap: var(--space-3); }
}
