/* ==========================================================================
   BASE / RESET
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* KEIN globales scroll-behavior: smooth mehr: Die Regel animierte nicht nur
   Anker-Klicks, sondern JEDE programmatische/Browser-interne Scroll-Korrektur
   (Hash-Load, Back/Forward, Clamping bei Dokumenthöhen-Änderungen) — auf
   Mobile machte das jede Korrektur zu sichtbarem Bouncen und das Scrollen
   "schwammig". Smooth-Scrolling für die Header-Anker-Buttons passiert jetzt
   gezielt per JS beim Klick (s. nav.js, spySections-Click-Handler), inkl.
   prefers-reduced-motion-Respekt. */
html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--color-background);
  color: var(--color-font-dark);
  font-family: var(--font-body);
  font-weight: var(--fw-regular);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  /* Deutsche Texte: lange Komposita sauber trennen statt überlaufen zu lassen */
  hyphens: auto;
  overflow-wrap: break-word;
}

img,
video,
picture,
svg {
  display: block;
  max-width: 100%;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration: none;
}

h1,
h2,
h3,
p {
  margin: 0;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-pixel-grotesk);
  /* Default für alle Überschriften: überschreibt den User-Agent-
     Stylesheet-Bold (h1–h6 sind dort direkt fett gesetzt, reine
     Vererbung von body würde das nicht schlagen). Einzelne Headings
     können das per eigener, spezifischerer Regel wieder überschreiben. */
  font-weight: var(--fw-regular);
}

p {
  /* Gleiche Schrift wie .text (components.css) – kt()-Felder rendern ihren
     Inhalt in <p>, eine direkte Deklaration hier gewinnt sonst gegen den
     von .text geerbten Wert. */
  font-family: var(--font-text);
  /* EINE Fließtext-Größe für alle <p>, unabhängig vom umgebenden Wrapper
     (.text, .section-introduction, ...) – vorher variierte die Größe je
     nach Eltern-Klasse (--fs-body vs. --fs-lead). --fs-lead statt --fs-body,
     da .section-introduction (components.css) ohnehin schon --fs-lead
     nutzte und diese Größe damit für die meisten Fließtexte bereits Standard
     war. Ausnahmen (Headlines/UI-Text, die aus Kirby-Sicht zufällig auch
     <p> sind): .intro-heading p (components.css) setzt sich per
     font-size:inherit zurück; .project-elevator (project.css) und
     .site-footer__copy (index.css) gewinnen automatisch, da Klassen-
     Selektoren spezifischer sind als der bloße Tag-Selektor hier. */
  font-size: var(--fs-lead);
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Sichtbarer Fokus-Ring für Tastaturnutzung (Buttons, Links) */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--color-font-dark);
  outline-offset: 3px;
}

/* ==========================================================================
   LAYOUT-PATTERN: full-bleed Section + contained Wrapper
   Sections decken die volle Viewportbreite ab (Hintergrundfarbe), der
   Inhalt wird über .wrapper auf --container-max zentriert.
   Segmente, die den Container komplett ignorieren sollen (Hero, Slider auf
   sehr breiten Viewports), verzichten einfach auf die .wrapper-Klasse.
   ========================================================================== */

.section {
  width: 100%;
}

.wrapper {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

/* Anker-Ziele (Latest, Services, …): kein scroll-margin-top mehr, seit der
   Header keinen eigenen Hintergrund mehr hat (siehe header.css) – er schwebt
   transparent über dem Content. Mit einem Offset bliebe sonst ein sichtbarer
   Streifen der vorherigen Section unterhalb des Headers stehen; die
   vorherige Section soll beim Anker-Scroll komplett aus dem Viewport
   verschwinden. */
.has-anchor-offset {
  scroll-margin-top: 0;
}

main > .section:first-child {
  padding-top: var(--header-height);
}

/* Sr-only Utility für zugängliche Labels ohne visuelle Sichtbarkeit */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Kreuz-Muster (.pattern-cross): schachbrettartig verteilte "+"-Zeichen.
   Modular: die Klasse auf ein BELIEBIGES Element setzen (braucht selbst
   keine eigene Größe/Position, füllt einfach seinen Elternrahmen). Läuft
   komplett auf ::before, damit das Element selbst weiterhin eigenen Inhalt
   tragen kann – ein Element, das bereits ein eigenes ::before nutzt,
   bekommt die Klasse deshalb über einen zusätzlichen Wrapper-Div statt
   direkt (s. Verwendung in site-header.php).

   Hintergrund bleibt transparent (kein Flächen-Fill) – es werden NUR die
   Kreuze selbst gezeichnet, der Rest des Elements zeigt das darunter-
   liegende Element durch.

   Fade (oben deckend -> unten transparent) sitzt bewusst NICHT in der
   Kreuz-Maske selbst, sondern als eigene mask-image-Regel auf dem
   Element (wirkt auf ::before UND alles andere im Element zusammen,
   da mask die komplette gerenderte Box betrifft). Getrennt, weil eine
   Zeilen-für-Zeile unterschiedliche Strichstärke (s. .pattern-cross-rows
   unten) viele einzelne, JEWEILS unfaded Instanzen braucht, die dann
   gemeinsam über EINE Fade-Maske am Gruppen-Wrapper ausgeblendet werden;
   .pattern-cross--no-fade schaltet den Fade pro Instanz ab.

   Einstellbar (pro Instanz per Inline-Style oder eigener Regel überschreiben):
     --pattern-color   Farbe der Kreuze
     --pattern-gap     Abstand zwischen zwei Kreuz-Mittelpunkten
     --pattern-size    Länge eines Kreuzes (beide Arme zusammen)
     --pattern-stroke  Strichstärke der Kreuze
     --pattern-fade-end  Wo die Ausblendung unten vollständig transparent
                         ist (% der Elementhöhe, Default 100% = unterer Rand)

   Technik: 4 sich überlagernde Gradient-Masken (je 2 pro Kreuz-Arm, X- und
   Y-Achse einzeln begrenzt, per mask-composite verschnitten) – dadurch
   Abstand und Größe unabhängig voneinander einstellbar, ohne Bild-Assets.
   Braucht mask-composite (Safari 15.4+, Chrome 120+, aktuelle Firefox). */
.pattern-cross {
  position: relative;
  mask-image: linear-gradient(to bottom, #000 0%, transparent var(--pattern-fade-end, 100%));
}
.pattern-cross--no-fade {
  mask-image: none;
}
.pattern-cross::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-color: var(--pattern-color, #444cf7);

  --pc-gap: var(--pattern-gap, 40px);
  --pc-size: var(--pattern-size, 14px);
  --pc-stroke: var(--pattern-stroke, 2px);

  mask-image:
    /* X auf Kreuzgröße begrenzt (Länge des waagrechten Arms) */
    repeating-linear-gradient(to right,
      transparent 0,
      transparent calc((var(--pc-gap) - var(--pc-size)) / 2),
      #000 calc((var(--pc-gap) - var(--pc-size)) / 2),
      #000 calc((var(--pc-gap) + var(--pc-size)) / 2),
      transparent calc((var(--pc-gap) + var(--pc-size)) / 2),
      transparent var(--pc-gap)),
    /* Y auf Strichstärke begrenzt (Dicke des waagrechten Arms) */
    repeating-linear-gradient(to bottom,
      transparent 0,
      transparent calc((var(--pc-gap) - var(--pc-stroke)) / 2),
      #000 calc((var(--pc-gap) - var(--pc-stroke)) / 2),
      #000 calc((var(--pc-gap) + var(--pc-stroke)) / 2),
      transparent calc((var(--pc-gap) + var(--pc-stroke)) / 2),
      transparent var(--pc-gap)),
    /* X auf Strichstärke begrenzt (Dicke des senkrechten Arms) */
    repeating-linear-gradient(to right,
      transparent 0,
      transparent calc((var(--pc-gap) - var(--pc-stroke)) / 2),
      #000 calc((var(--pc-gap) - var(--pc-stroke)) / 2),
      #000 calc((var(--pc-gap) + var(--pc-stroke)) / 2),
      transparent calc((var(--pc-gap) + var(--pc-stroke)) / 2),
      transparent var(--pc-gap)),
    /* Y auf Kreuzgröße begrenzt (Länge des senkrechten Arms) */
    repeating-linear-gradient(to bottom,
      transparent 0,
      transparent calc((var(--pc-gap) - var(--pc-size)) / 2),
      #000 calc((var(--pc-gap) - var(--pc-size)) / 2),
      #000 calc((var(--pc-gap) + var(--pc-size)) / 2),
      transparent calc((var(--pc-gap) + var(--pc-size)) / 2),
      transparent var(--pc-gap));
  mask-composite: intersect, add, intersect, add;
}

/* .pattern-cross-rows: Gruppen-Wrapper für mehrere gestapelte Kreuz-Zeilen
   MIT unterschiedlicher Strichstärke pro Zeile (dick oben, dünn unten – pro
   Zeile in PHP berechnet, s. partials/pattern-cross-rows.php). Jede Zeile
   ist eine eigene .pattern-cross--no-fade-Instanz (kein eigener Fade); die
   EINE Ausblendung fürs gesamte Muster sitzt hier am Wrapper.
   --pattern-opacity: zusätzliche globale Transparenz fürs GESAMTE Muster
   (alle Zeilen zusammen), unabhängig von --pattern-color/--pattern-fade-end –
   z.B. über den $opacity-Parameter des Snippets steuerbar. pointer-events:
   none auf dem Wrapper macht das GESAMTE Muster (samt aller Zeilen-Kinder)
   klick-/hover-durchlässig – rein dekorativ, soll nie Klicks auf darunter-
   oder darüberliegende echte Inhalte (Hero-Video, Header-Buttons …) abfangen. */
.pattern-cross-rows {
  /* Statisches Muster (kein Video-/Bild-Invert mehr, s. Git-Historie) –
     40% Deckkraft als fester Default, per --pattern-opacity überschreibbar. */
  opacity: var(--pattern-opacity, 0.4);
  pointer-events: none;
}
.pattern-cross-rows .pattern-cross {
  position: absolute;
  left: 0;
  right: 0;
}

/* Platzierung im Hero (s. blocks/hero.php): läuft bewusst NICHT als
   position:fixed über die ganze Seite (das würde beim Scrollen dauerhaft
   über spätere Bilder/Texte liegen bleiben, s. Bugreport), sondern als
   position:sticky innerhalb von .hero – bleibt oben am Viewport-Rand
   "kleben", solange der Hero durchgescrollt wird, und löst sich danach
   ganz normal, sobald das Hero-Ende den oberen Rand erreicht (verschwindet
   also garantiert, sobald man am Hero vorbei ist). Braucht overflow:clip
   statt overflow:hidden auf .hero (s. hero.css) – "hidden" würde .hero
   selbst zum nächsten scrollenden Vorfahren machen und sticky wirkungslos
   machen. z-index:1 setzt es sichtbar ÜBER .hero__media (Video/Bild, kein
   eigenes z-index), aber unterhalb von .hero::after (dem bestehenden
   dunklen Verlaufs-Overlay, das als zuletzt gemaltes generiertes Element
   automatisch obenauf liegt). */
.hero .pattern-cross-rows {
  position: sticky;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1;
  mask-image: linear-gradient(to bottom, #000 0%, transparent var(--pattern-fade-end, 100%));
}
