/* ============================================================
   20 · UTILITIES — projektweit wiederverwendbar
   ------------------------------------------------------------
   Alles hier ist kontextfrei und darf in jeder Sektion und jeder
   Komponente verwendet werden. Nichts hier ist sektionsspezifisch
   (CLAUDE.md).

   Breakpoints: 600 / 768 / 1024 / 1280, nur min-width.
   ============================================================ */

/* ---------- Eyebrow / Kicker ---------- */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--rule-gap);
  margin-bottom: 22px;
  color: var(--green);
  font-size: var(--fs-200);
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.eyebrow::before {
  content: "";
  flex: none;
  width: var(--rule-w);
  height: var(--rule-h);
  background: var(--amber);
}

/* Zwei gleichrangige Varianten, benannt nach der Schriftfarbe, die sie
   erzeugen: `--light` fuer dunkle Flaechen, `--deep` fuer helle. Vorher gab es
   nur `--light`, und die helle Spalte des geteilten Kopfes faerbte sie aus der
   Sektion heraus wieder dunkel -- eine Variante, die man nicht mehr lesen
   konnte, ohne ihren Kontext zu kennen. */
.eyebrow--light,
.eyebrow--deep {
  margin-bottom: 20px;
  font-weight: 700;
}

.eyebrow--light {
  color: var(--white);
}

.eyebrow--deep {
  color: var(--green-deep);
}

/* ---------- Sektionstitel ---------- */
.section-title {
  color: var(--ink);
  font-size: var(--fs-h2);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.section-title strong {
  color: var(--green);
  font-weight: 800;
}

/* Fuer Ueberschriften in einer schmalen Spalte oder mit vielen Worten --
   etwa die Projektbeschreibung, deren Kopf in 5 von 12 Rasterspalten steht. */
.section-title--compact {
  font-size: var(--fs-h2-sm);
  line-height: 1.2;
}

.section-title--light {
  color: var(--white);
}

.section-title--light strong,
.section-title--light em {
  color: var(--amber-soft);
  font-style: normal;
  font-weight: 800;
}

/* ---------- Button ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 16px 30px;
  border: 0;
  white-space: nowrap;
  font-family: inherit;
  font-size: var(--fs-300);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    transform 0.2s var(--ease),
    background var(--dur-fast),
    color var(--dur-fast),
    border-color var(--dur-fast);
}

.btn:active {
  transform: scale(0.98);
}

/* Gefuellte Flaechen mit weisser Schrift nutzen --amber-strong statt --amber:
   Auf dem helleren Ton erreicht 14 px fette Versalschrift nur 3,6 : 1 und
   verfehlt damit die Anforderung von 4,5 : 1. Der Unterschied der beiden
   Toene ist mit blossem Auge kaum zu erkennen. */
.btn--amber {
  background: var(--amber-strong);
  color: var(--white);
}

.btn--amber:hover {
  background: var(--amber-deep);
}

.btn--green {
  background: var(--green);
  color: var(--white);
}

.btn--green:hover {
  background: var(--green-deep);
}

/* Umrissvariante: zurueckhaltender als die gefuellten Schaltflaechen,
   fuer nachgeordnete Aktionen. Rahmen in Amber, Schrift im dunkleren
   Amber-Ton -- der helle traegt als Text zu wenig Kontrast. */
.btn--outline {
  background: none;
  border: 1.5px solid var(--amber);
  color: var(--amber-deep);
}

.btn--outline:hover {
  background: var(--amber-strong);
  border-color: var(--amber-strong);
  color: var(--white);
}

/* ---------- Textlink mit Pfeil ---------- */
.textlink {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 28px;
  color: var(--green);
  font-size: var(--fs-300);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.textlink:hover {
  color: var(--amber-deep);
}

/* Variante ohne Vorabstand, wenn der Link direkt an einem Element klebt. */
.textlink--tight {
  margin-top: 0;
}

/* Kartenlink zur Adresse -- ein Textlink, keine eigene Komponente. */
/* Der Kartenlink steht auf heller Flaeche und dreht die Farben des Textlinks
   um: ruhend amber, bei Mauskontakt gruen. Das stand bis zum 2026-10-01 als
   Umfaerbung in 50-sections.css -- dieselbe Angabe, nur an einer Stelle, an der
   sie die Ebenentrennung brach. */
.textlink--map {
  margin-top: 12px;
  color: var(--amber-deep);
  font-size: var(--fs-200);
  letter-spacing: 0.08em;
}

.textlink--map:hover {
  color: var(--green-deep);
}

/* Variante als Schaltflaeche: derselbe Textlink, nur fuehrt er nirgendwohin,
   sondern klappt etwas auf. Die Vorgaben des Browsers fuer <button> muessen
   dafuer weichen -- Flaeche, Rahmen und Schrift kaemen sonst vom
   Betriebssystem und nicht aus dem Stylesheet. */
.textlink--toggle {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--fs-300);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}

/* Zeichen fuer den Zustand. Ein eigenes Element und nicht .arr: Der Pfeil
   eines Links rueckt beim Hover zur Seite, dieser dreht sich beim
   Aufklappen -- zwei Regeln auf derselben Eigenschaft. */
.textlink__sign {
  display: inline-block;
  transition: transform var(--dur-fast) var(--ease);
}

.textlink--toggle[aria-expanded="true"] .textlink__sign {
  transform: rotate(180deg);
}

/* Symbol vor dem Text. Waechst mit der Schriftgroesse des Links und erbt
   ueber currentColor dessen Farbe -- auch im Hover. */
.textlink__icon {
  flex: none;
  width: 1.3em;
  height: 1.3em;
}

/* ---------- Pfeil-Glyphe ---------- */
.arr {
  transition: transform var(--dur-fast) var(--ease);
}

.btn:hover .arr,
.textlink:hover .arr {
  transform: translateX(5px);
}

.textlink--back:hover .arr {
  transform: translateX(-5px);
}

/* ---------- Reveal beim Scrollen ---------- */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity var(--dur-slow) var(--ease),
    transform var(--dur-slow) var(--ease);
}

.reveal.is-in {
  opacity: 1;
  transform: none;
}

/* Maskierter Reveal: die Zeile steigt aus dem Overflow auf.
   Wird auch von der Hero-Ueberschrift genutzt -- die Vorlage hatte die
   Technik dort ein zweites Mal nachgebaut. */
.rmask {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

.rmask__in {
  display: block;
  transform: translateY(115%);
  transition: transform 0.85s var(--ease);
}

.rmask.is-in .rmask__in {
  transform: none;
}

/* Variante fuer Inhalte, die beim Laden schon sichtbar sind: Ein
   Scroll-Trigger kaeme dort zu spaet. Gleiche Maskengeometrie, nur ein
   anderer Ausloeser -- deshalb Modifier statt zweiter Technik. */
@media (prefers-reduced-motion: no-preference) {
  .rmask--onload .rmask__in {
    animation: fay-line-rise 0.95s var(--ease) 0.1s forwards;
  }

  .rmask--onload:nth-child(2) .rmask__in {
    animation-delay: 0.24s;
  }

  @keyframes fay-line-rise {
    to { transform: none; }
  }
}

@media (prefers-reduced-motion: reduce) {
  .rmask--onload .rmask__in {
    transform: none;
  }
}

/* Grosser FAY-Schriftzug als Flaeche hinter dem Inhalt.
   ------------------------------------------------------------
   Lag bis 2026-08-18 als .stats__watermark in der Kennzahlen-Sektion. Seit
   auch der Nachhaltigkeits-Abschnitt ihn traegt, gehoert er hierher -- eine
   Kopie waeren zehn Zeilen doppelt.

   Braucht einen Elternteil mit position: relative und overflow: hidden.
   Dafuer gibt es .section--watermark in 40-components.css; .stats bringt
   beides schon selbst mit. */
.watermark {
  position: absolute;
  right: -3vw;
  bottom: -9vw;
  color: var(--watermark);
  font-size: var(--fs-watermark);
  font-weight: 800;
  letter-spacing: -0.05em;
  line-height: 1;
  user-select: none;
  pointer-events: none;
}

/* Clip-Reveal fuer Bildkacheln: Vorhang von oben nach unten. */
.rimg {
  clip-path: inset(0 0 100% 0);
  transition: clip-path var(--dur-reveal) var(--ease);
}

.rimg.is-in {
  clip-path: inset(0 0 0 0);
}

/* Fokuspunkt: welcher Teil eines Bildes den Zuschnitt ueberlebt.
   ------------------------------------------------------------
   Jede Flaeche, die ein Projektbild zeigt, beschneidet es -- das Material ist
   16:9, die Flaechen sind es nicht. Ohne Angabe nimmt object-fit die Mitte,
   und bei Architekturaufnahmen ist das oft die falsche Wahl.

   Zwei Achsen, weil object-position immer nur auf der Achse wirkt, die
   UEBERLAEUFT. Bei 16:9-Material heisst das:

     Flaeche schmaler als 16:9  ->  waagerecht beschnitten, nur x wirkt
     Flaeche breiter als 16:9   ->  senkrecht beschnitten, nur y wirkt

   Gemessen sind das Projektkopf (1,06-1,50), Mosaik (1,00-1,50),
   Archivkachel (1,50) und der Startseiten-Hero -- alle waagerecht -- und der
   Archiv-Seitenkopf (2,08-3,10) als einziger senkrecht. Die Redaktion muss
   das nicht wissen: Sie setzt einen Punkt je Bild, und je Flaeche greift die
   Achse, die dort ueberlaeuft.

   Die Zahl ist die Lage in Prozent, genau wie sie in object-position landet.
   Fuenf Stufen je Achse; die Mitte ist die Vorgabe und braucht keine Klasse.

   Wert per Klasse, nicht per Inline-Style -- dasselbe Muster wie .d-1 bis
   .d-4 weiter unten. Gesetzt wird zentral in fay_focus_class()
   (inc/template-tags.php). */
.focus-x-0   { --focus-x: 0%; }
.focus-x-25  { --focus-x: 25%; }
.focus-x-75  { --focus-x: 75%; }
.focus-x-100 { --focus-x: 100%; }

.focus-y-0   { --focus-y: 0%; }
.focus-y-25  { --focus-y: 25%; }
.focus-y-75  { --focus-y: 75%; }
.focus-y-100 { --focus-y: 100%; }

.focus-x-0,
.focus-x-25,
.focus-x-75,
.focus-x-100,
.focus-y-0,
.focus-y-25,
.focus-y-75,
.focus-y-100 {
  object-position: var(--focus-x, 50%) var(--focus-y, 50%);
}

/* Gestaffelte Verzoegerung. Ein Set fuer alle Reveal-Arten -- die Vorlage
   hatte dafuer zwei parallele Sets (.reveal-d* und .rimg-d*). */
/* Drei Stufen und nicht vier: Jede erzeugende Stelle rechnet `$index % 4` und
   gibt die Klasse nur bei einem Rest groesser null aus -- moeglich sind damit
   d-1 bis d-3. Eine vierte Stufe konnte nie entstehen. */
.d-1 { --d: 1; }
.d-2 { --d: 2; }
.d-3 { --d: 3; }

.d-1,
.d-2,
.d-3 {
  transition-delay: calc(var(--d) * var(--delay-step));
}

@media (prefers-reduced-motion: reduce) {
  .reveal,
  .rmask__in,
  .rimg,
  .d-1,
  .d-2,
  .d-3 {
    transition: none;
    transition-delay: 0s;
  }

  .rimg {
    clip-path: none;
  }
}
