/* ==========================================================================
   style.css — Grundlagen: Reset, Typografie, Raster, Hilfsklassen
   --------------------------------------------------------------------------
   WOFÜR: Alles, was auf jeder Seite gilt und keinem einzelnen Baustein
          gehört. Bausteine (Buttons, Karten, Formular) stehen in
          components.css, Header/Footer in layout.css, Seitenabschnitte in
          pages.css.
   ABHÄNGIG VON: tokens.css (muss vorher eingebunden sein)
   BEIM ÄNDERN BEACHTEN: Hier stehen bewusst nur Element- und Utility-
          Selektoren mit niedriger Spezifität. Wer hier .card oder .btn
          anfasst, bricht die Kaskade in components.css.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Reset — nur das Nötige
   -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* clip statt hidden: verhindert waagerechtes Scrollen, ohne einen
     Scroll-Container zu erzeugen — sonst greift position: sticky nicht */
  overflow-x: clip;
  /* Sprungmarken landen nicht unter dem fixierten Header */
  scroll-padding-top: 6.5rem;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-stretch: var(--width-text);
  line-height: var(--lh-body);
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  /* Kein overflow-x: hidden hier. Das würde den Body zum Scroll-Container
     machen und damit position: sticky brechen — betroffen wären der Header
     und die Registerreiter am Blattrand. Gegen waagerechten Überlauf steht
     overflow-x: clip am <html>; clip erzeugt keinen Scroll-Container. */
}

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

img { height: auto; }

button,
input,
select,
textarea { font: inherit; color: inherit; }

/* Kein Doppeltipp-Zoom auf Bedienelementen: der Browser muss nach dem
   ersten Tipp nicht auf einen zweiten warten. Zoomen per Fingerspreizen
   bleibt möglich. */
a,
button,
input,
select,
textarea,
label,
summary { touch-action: manipulation; }

ul, ol { margin: 0; padding: 0; }

/* --------------------------------------------------------------------------
   2. Typografie
   Grundprinzip: großer Sprung zwischen Überschrift und Text, enge Zeilen
   oben, weite Zeilen unten. Überschriften laufen breit (wdth 112 %),
   Labels laufen schmal (wdth 78 %).
   -------------------------------------------------------------------------- */
h1, h2, h3, h4 {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-brand);
  font-weight: 700;
  font-stretch: var(--width-display);
  letter-spacing: var(--ls-display);
  line-height: var(--lh-heading);
  text-wrap: balance;   /* verhindert Schusterjungen in Überschriften */
}

h1 { font-size: var(--fs-h1); line-height: var(--lh-display); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); letter-spacing: -0.015em; }
h4 { font-size: var(--fs-h4); letter-spacing: -0.01em; }

p { margin: 0 0 var(--sp-4); text-wrap: pretty; }

p:last-child { margin-bottom: 0; }

a {
  color: var(--green-text);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color var(--dur-fast) var(--ease);
}

@media (hover: hover) {
  a:hover { color: var(--ink); }
}

strong, b { font-weight: 700; }

small { font-size: var(--fs-small); }

/* Lauftext-Klasse für Einleitungen unter Überschriften. Die Einleitung
   bleibt gedämpft, starke Wörter tragen die Tinte — dasselbe Muster wie
   die Belegzeile im Hero. */
.lead {
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: var(--text-muted);
  max-width: 46ch;
}

.lead strong { color: var(--ink); }

/* --------------------------------------------------------------------------
   Registerreiter
   --------------------------------------------------------------------------
   Der Abschnittsname sitzt nicht als Etikett über der Überschrift, sondern
   als Griffregister am Blattrand — wie die Reiter in einem Objektordner.
   Auf breiten Schirmen läuft er senkrecht am linken Rand mit und bleibt
   sichtbar, solange der Abschnitt läuft; man weiß beim Scrollen also
   jederzeit, wo man ist. Darunter, wo der Rand fehlt, wird daraus eine
   Registerlasche: eine feine Linie über die Breite, der Name sitzt am Ende.

   Aufbau im HTML:
     <p class="register">
       <span class="register__rule"></span>
       <span class="register__name">Leistungen</span>
     </p>
   -------------------------------------------------------------------------- */
.register {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin: 0 0 var(--sp-6);
  font-family: var(--font-label);
  font-size: 0.6875rem;
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--green-text);
}

/* Die Linie nimmt den freien Raum, der Name sitzt an ihrem Ende. */
.register__rule {
  flex: 1;
  height: 1px;
  background: var(--line-green);
}

.register__name { flex: none; }

/* Ab dieser Breite bleibt links neben dem Raster genug Platz für den
   senkrechten Reiter. Darunter bleibt es bei der Lasche. */
@media (min-width: 1400px) {
  /* Nur Abschnitte, die über die volle Breite laufen. Auf eingerückten
     Farbflächen (.section--rounded, .cta) säße der Reiter neben der Fläche
     statt an ihr — dort bleibt die Lasche. */
  .section:not(.section--rounded):not(.cta) .register,
  .page-head .register {
    position: absolute;
    left: calc((100% - var(--container)) / 2 - 2.5rem);
    top: var(--section);
    bottom: var(--section);
    width: 1px;
    margin: 0;
    flex-direction: column;
    align-items: center;
    gap: 0;
    background: var(--line-green);
  }

  .section:not(.section--rounded):not(.cta) .register .register__rule,
  .page-head .register .register__rule { display: none; }

  /* Der Name läuft mit, solange der Abschnitt im Bild ist. Der Hintergrund
     unterbricht die Linie an seiner Stelle — deshalb muss er zur Fläche des
     Abschnitts passen, siehe die drei Sonderfälle darunter. */
  .section:not(.section--rounded):not(.cta) .register .register__name,
  .page-head .register .register__name {
    position: sticky;
    top: calc(var(--header-h) + var(--sp-6));
    writing-mode: vertical-rl;
    padding: var(--sp-4) 0;
    background: var(--bg);
  }

  .section--paper .register .register__name { background: var(--surface); }
}

/* Kleines Label für Panels und Randspalten. Bewusst ohne Strich davor:
   dort markiert es kein Kapitel, es beschriftet nur eine Liste. */
.eyebrow {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

.eyebrow--on-soft { color: var(--green-text); }

/* Grüne Auszeichnung eines EINZELNEN Wortes in einer Überschrift.
   Kein Textkontrast-Problem, weil nur der Unterstrich grün ist. */
.mark {
  /* Das Kernwort steht im dunklen Markengrün; alle drei Sekunden läuft ein
     hellerer Schimmer hindurch. Der Verlauf wird per background-clip auf die
     Buchstaben beschnitten, deshalb braucht es transparente Schriftfarbe —
     die Ausgangsfarbe darunter bleibt als Rückfall stehen, falls ein Browser
     background-clip: text nicht kennt. */
  color: var(--green-text);
  white-space: nowrap;
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
  .mark {
    /* Die Grundfarbe liegt als background-color darunter und wird ebenfalls
       auf die Buchstaben beschnitten. Ohne sie bliebe der Teil des Wortes
       unsichtbar, über dem der wandernde Verlauf gerade nicht steht. */
    background-color: var(--green-text);
    background-image: linear-gradient(100deg,
      var(--green-text) 42%,
      var(--green-light) 50%,
      var(--green-text) 58%);
    background-repeat: no-repeat;
    background-size: 260% 100%;
    background-position: 130% 0;
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
            color: transparent;
    animation: mark-shimmer 3s var(--ease) infinite;
  }
}

/* Die ersten zwei Drittel steht der Verlauf still — dadurch schimmert es
   einmal alle drei Sekunden statt permanent zu wandern. */
@keyframes mark-shimmer {
  0%, 62% { background-position: 130% 0; }
  100%    { background-position: -30% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .mark { animation: none; background-position: 130% 0; }
}

/* --------------------------------------------------------------------------
   3. Raster
   .wrap        Standardcontainer
   .wrap--narrow Lesebreite für lange Texte
   .grid        12-Spalten-Raster; Abschnitte greifen einzelne Spalten ab.
                Absichtlich asymmetrisch belegt statt dreimal 1/3.
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap--narrow { max-width: calc(var(--container-narrow) + 2 * var(--gutter)); }

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--sp-6);
}

@media (max-width: 900px) {
  .grid { grid-template-columns: repeat(6, 1fr); gap: var(--sp-5); }
}

@media (max-width: 600px) {
  .grid { grid-template-columns: 1fr; }
  .grid > * { grid-column: 1 / -1 !important; }
}

/* Abschnittsabstände. Drei Stufen statt einer — siehe tokens.css. */
.section { position: relative; padding-block: var(--section); }

/* Getönte Abschnitte sitzen als abgerundete Fläche im Weiß, statt als
   randloses Band durchzulaufen. Das nimmt der Seite die Strenge. */
.section--rounded {
  border-radius: var(--radius-lg);
  margin-inline: var(--gutter);
}

@media (max-width: 700px) {
  .section--rounded { margin-inline: 0; border-radius: 0; }
}
.section--tight { padding-block: var(--section-tight); }
.section--wide { padding-block: var(--section-wide); }

/* Farbflächen für ganze Abschnitte.
   Die Seite steht auf Weiß. Als Wechsel gibt es genau zwei Töne:
   eine kaum getönte helle Fläche und eine grün getönte. Braun kommt
   ausschließlich als Schriftfarbe vor, nie als Hintergrund. */
/* Weiße Sektion: hebt sich nach oben vom Off-White-Grund ab */
.section--paper {
  background: var(--surface);
  border-block: 1px solid var(--line);
}

.section--soft {
  background: var(--green-soft);
  color: var(--ink);
}

.section--soft .eyebrow { color: var(--green-text); }
.section--soft p { color: var(--ink-80); }
.section--soft a { color: var(--green-text); }
@media (hover: hover) {
  .section--soft a:hover { color: var(--ink); }
}

/* --------------------------------------------------------------------------
   5. Barrierefreiheit
   -------------------------------------------------------------------------- */

/* Sichtbarer Fokusring auf allem, was Fokus bekommt */
:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius);
}

.section--soft :where(a, button, summary):focus-visible {
  outline-color: var(--focus);
}

/* Nur für Screenreader */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Sprungmarke zum Inhalt — erste fokussierbare Stelle jeder Seite */
.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: var(--z-skip);
  transform: translateY(-120%);
  padding: var(--sp-3) var(--sp-5);
  background: var(--ink);
  color: var(--white);
  font-weight: 600;
  text-decoration: none;
}

.skip-link:focus {
  transform: translateY(0);
  color: var(--white);
}

/* Nutzer, die Bewegung reduzieren wollen, bekommen keine. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0.01ms !important;   /* auch gestaffelte Einträge
                                              (z. B. Kontakt-Schnellwahl)
                                              erscheinen sofort */
  }
}

/* --------------------------------------------------------------------------
   6. Hilfsklassen — sparsam gehalten
   -------------------------------------------------------------------------- */
.stack > * + * { margin-top: var(--sp-4); }
.stack-lg > * + * { margin-top: var(--sp-6); }

.text-muted { color: var(--text-muted); }
.nowrap { white-space: nowrap; }

/* Listen ohne Punkte, aber mit Semantik */
.list-plain { list-style: none; }

/* Druckausgabe: Navigation und schwebende Elemente weg */
@media print {
  .site-header,
  .site-footer,
  .contact-fab,
  .skip-link { display: none !important; }
  body { font-size: 11pt; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
}

/* ==========================================================================
   7. Bewegung
   Zwei Prinzipien: Bewegung zeigt Struktur (was gehört zusammen, was kommt
   als Nächstes) und ist nie länger als eine halbe Sekunde. Alles hier
   greift nur, wenn JavaScript läuft und der Nutzer Bewegung nicht abbestellt
   hat — der Startzustand steht bewusst unter .js, damit ohne JavaScript
   nichts unsichtbar bleiben kann.
   Gesteuert von assets/js/reveal.js.

   EIN STIL FÜR ALLES, was auf eine Handlung antwortet: pop-in — ein
   kleiner Hub von unten mit Überschwung (--ease-spring), Listen um je
   50–80 ms gestaffelt, Symbole drehen sich mit derselben Feder aus dem
   und ins Bild (Menü-Knopf, Kontakt-Schnellwahl, FAQ-Plus, Caret).
   rise-in bleibt den ruhigen Einblendungen beim Laden und Scrollen
   vorbehalten.
   ========================================================================== */

/* --- Einblenden beim Scrollen ------------------------------------------- */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur-slow) var(--ease-out) var(--reveal-delay, 0ms),
              transform var(--dur-slow) var(--ease-out) var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}

.js [data-reveal][data-revealed="true"] {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Seitliche Variante für versetzte Text-Bild-Blöcke. Auf schmalen
   Viewports fällt sie auf die senkrechte Bewegung zurück: dort stehen die
   Blöcke ohnehin untereinander, und eine waagerechte Verschiebung würde
   den Inhalt über den Rand schieben und die Seite breiter machen als das
   Fenster. */
.js [data-reveal="left"] { transform: translateX(-24px); }
.js [data-reveal="right"] { transform: translateX(24px); }

@media (max-width: 900px) {
  .js [data-reveal="left"],
  .js [data-reveal="right"] { transform: translateY(18px); }
}

/* --- Eingangssequenz im Hero -------------------------------------------
   Läuft einmal beim Laden. Die Reihenfolge folgt der Leserichtung:
   Kapitelzeile, Überschrift, Belege, Einleitung, Aktionen, Datenpanel. */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

.js .hero__intro > *,
.js .hero__aside {
  animation: rise-in 620ms var(--ease-out) both;
}

.js .hero__intro > .register     { animation-delay: 40ms; }
.js .hero__intro > h1            { animation-delay: 110ms; }
.js .hero__intro > .hero__proof  { animation-delay: 220ms; }
.js .hero__intro > .lead         { animation-delay: 300ms; }
.js .hero__intro > .actions      { animation-delay: 380ms; }
.js .hero__aside                 { animation-delay: 460ms; }

/* Die Belege im Hero kommen einzeln nach */
@keyframes pop-in {
  from { opacity: 0; transform: translateY(8px) scale(0.96); }
  to   { opacity: 1; transform: none; }
}

.js .hero__proof li {
  animation: pop-in 420ms var(--ease-spring) both;
}

.js .hero__proof li:nth-child(1) { animation-delay: 260ms; }
.js .hero__proof li:nth-child(2) { animation-delay: 330ms; }
.js .hero__proof li:nth-child(3) { animation-delay: 400ms; }

/* Die Positionen des Leistungsverzeichnisses kommen einzeln nach,
   die Summe zieht zuletzt den Schlussstrich. Das Streichen der
   Problemzeilen (ledger.js) beginnt erst danach, bei etwa 1,6 s. */
.js .hero__aside .ledger__list li { animation: pop-in 420ms var(--ease-spring) both; }
.js .hero__aside .ledger__list li:nth-child(1) { animation-delay: 560ms; }
.js .hero__aside .ledger__list li:nth-child(2) { animation-delay: 640ms; }
.js .hero__aside .ledger__list li:nth-child(3) { animation-delay: 720ms; }
.js .hero__aside .ledger__list li:nth-child(4) { animation-delay: 800ms; }
.js .hero__aside .ledger__sum {
  animation: rise-in 620ms var(--ease-out) both;
  animation-delay: 900ms;
}

/* --- Feinheiten ---------------------------------------------------------- */

/* Buttons geben beim Drücken nach */
.btn:active { transform: translateY(1px); }

.btn--primary {
  transition: background var(--dur-fast) var(--ease),
              box-shadow var(--dur) var(--ease),
              transform var(--dur-fast) var(--ease);
}

@media (hover: hover) {
  .btn--primary:hover { box-shadow: var(--shadow-card); transform: translateY(-1px); }
}

/* Pfeile in Links wandern ein Stück mit */
.btn svg,
.card__more svg { transition: transform var(--dur) var(--ease); }
@media (hover: hover) {
  .btn:hover svg { transform: translateX(3px); }
}

/* Brotkrumen */
.breadcrumb a { transition: color var(--dur-fast) var(--ease); }

/* Bilder in Karten atmen beim Hovern (bereits in components.css),
   hier nur die Kurve angeglichen */
.card__media img { transition: transform 600ms var(--ease-out); }

/* Der Header wird beim Scrollen etwas flacher. Kaum bemerkbar, gibt der
   Seite aber ein Gefühl von Reaktion. */
.site-header__inner { transition: min-height var(--dur) var(--ease); }
.site-header--scrolled .site-header__inner { min-height: 4rem; }

/* Mobilmenü: Punkte federn gestaffelt ein — dieselbe Bewegung wie die
   Belege im Hero, die Positionen im Leistungsverzeichnis und die
   Kontakt-Schnellwahl. */
@media (max-width: 900px) {
  .js .nav[data-open="true"] .nav__item,
  .js .nav[data-open="true"] .nav__contact {
    animation: pop-in 420ms var(--ease-spring) both;
  }
  .js .nav[data-open="true"] .nav__item:nth-child(1) { animation-delay: 80ms; }
  .js .nav[data-open="true"] .nav__item:nth-child(2) { animation-delay: 140ms; }
  .js .nav[data-open="true"] .nav__item:nth-child(3) { animation-delay: 200ms; }
  .js .nav[data-open="true"] .nav__contact { animation-delay: 260ms; }
}

/* Sämtliche Bewegung dieses Abschnitts wird von der globalen
   prefers-reduced-motion-Regel weiter oben abgeschaltet. Zusätzlich sorgt
   reveal.js dafür, dass die Elemente dann sofort sichtbar sind. */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; }
  .js .hero__intro > *,
  .js .hero__aside,
  .js .hero__proof li,
  .js .hero__aside .ledger__list li,
  .js .hero__aside .ledger__sum { animation: none; }
}
