/* Reset, Grundtypografie und die wenigen globalen Layout-Regeln.
   Alles Komponentenspezifische lebt im jeweiligen Shadow Root. */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
/* Lenis übernimmt das Scrollen; natives smooth würde dagegen arbeiten. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

body {
  margin: 0;
  background: var(--surface);
  color: var(--on-surface);
  font-family: var(--font);
  font-size: var(--t-body-md);
  line-height: 1.4;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Linsen-Vignette: radialer Scrim von der Mitte nach außen, wie im
   Design-System unter "Scrims" gefordert. Liegt hinter allem. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(120% 80% at 50% 0%, rgb(255 180 0 / 0.045), transparent 60%),
    radial-gradient(100% 100% at 50% 50%, transparent 45%, rgb(0 0 0 / 0.55) 100%);
}

img, svg, video { display: block; max-width: 100%; }
button { font: inherit; color: inherit; }

a { color: var(--primary); text-decoration-thickness: 1px; text-underline-offset: 3px; }

:focus-visible {
  outline: 2px solid var(--primary-container);
  outline-offset: 3px;
  border-radius: var(--r);
}

::selection { background: var(--primary-container); color: var(--on-primary); }

/* Scrollbar dezent halten, damit das Letterboxing nicht bricht */
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: var(--surface-lowest); }
::-webkit-scrollbar-thumb { background: var(--surface-highest); border-radius: var(--r-full); }
::-webkit-scrollbar-thumb:hover { background: var(--outline-variant); }

/* Der Skip-Link wird ausschließlich per Tastatur ausgelöst — und
   tastaturausgelöste Aktionen bekommen keine Animation. Wer sich per Tab
   durch die Seite bewegt, will sofort sehen, wo er ist, nicht auf einen
   einfahrenden Kasten warten. Positioniert wird über transform statt über
   top: `top` ist eine Layout-Eigenschaft und würde ein Reflow auslösen. */
.skip-link {
  position: absolute;
  left: var(--s-md);
  top: var(--s-md);
  z-index: 200;
  padding: var(--s-sm) var(--s-md);
  background: var(--primary-container);
  color: var(--on-primary);
  border-radius: var(--r-lg);
  font-weight: 700;
  text-decoration: none;
  transform: translateY(calc(-100% - var(--s-md) - 8px));
}
.skip-link:focus { transform: none; }

main { position: relative; z-index: 1; }

/* Custom Elements sind bis zu ihrem Upgrade 0 Pixel hoch. Ohne diese
   Reservierung sitzt die Work-Sektion im allerersten Frame ganz oben im
   Viewport und wird anschließend vom aufklappenden Hero um eine volle
   Bildschirmhöhe nach unten geschoben. Genau das war der komplette CLS
   (0,88 von 0,881 in einem einzigen Shift auf section#work).

   Die Werte müssen mit dem übereinstimmen, was die Komponenten später
   tatsächlich einnehmen — sonst verschiebt sich die Differenz. */
hero-stage {
  display: block;
  min-height: var(--hero-h, 100svh);
}
capability-ticker {
  display: block;
  min-height: 46px;   /* 12px Zeile + 2×16px Innenabstand + 2×1px Rahmen */
}

/* Sektionen sind "Szenen" — großzügiger vertikaler Rhythmus, aber die
   Abstände addieren sich zwischen zwei Sektionen, deshalb gedeckelt. */
.section {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: clamp(56px, 7vw, 96px) var(--gutter);
}

.section-head { margin-bottom: var(--s-xl); }

.eyebrow {
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--primary-dim);
  margin: 0 0 var(--s-md);
}

h2.display {
  font-size: var(--t-display-md-size);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.02em;
  margin: 0 0 var(--s-md);
}

.lede {
  font-size: var(--t-body-lg);
  line-height: 1.5;
  color: var(--on-surface-variant);
  max-width: 46ch;
  margin: 0;
}

/* Das Auszeichnungs-Badge wartet als Light-DOM-Kind von work-grid im
   Dokument, bis die Komponente es in die passende Projektkarte einhängt
   (Begründung im Kommentar in index.html). Bis dahin — und dauerhaft, falls
   JS ausfällt — bleibt es unsichtbar: Ohne Karten darunter stünde es sonst
   allein unter der Sektionsüberschrift.

   Sein sichtbares CSS lebt in work-grid.js. Es muss dort liegen, nicht hier:
   Sobald der Knoten in die Karte wandert, gehört er zum Shadow Tree von
   work-grid, und Dokument-Stylesheets reichen dort nicht hinein. */
work-grid > [slot="badge"] { display: none; }

/* Reveal-Grundzustand. Wird von GSAP übernommen; ohne JS bleibt nichts
   unsichtbar liegen — die .no-js-Regel unten setzt alles wieder sichtbar.

   Kein dauerhaftes will-change: Die Reveals laufen mit `once: true` genau
   einmal, danach hielte das Flag für den Rest der Sitzung eine eigene
   Compositor-Ebene pro Element offen. GSAP setzt will-change ohnehin
   selbst für die Dauer des Tweens. */
.reveal { opacity: 0; }
html.no-motion .reveal, html.no-js .reveal { opacity: 1; }

/* Ohne JavaScript darf weder ein Vorhang noch ein Ersatzcursor im Weg
   liegen — beide brauchen JS, um je wieder zu verschwinden. */
html.no-js site-preloader,
html.no-js cursor-glow { display: none !important; }

/* Reduced Motion heißt weniger und sanfter — nicht gar nichts. Farb-,
   Bloom- und Deckkraftwechsel bleiben deshalb stehen: Sie erklären
   Zustände, ohne dass sich etwas bewegt. Weg müssen die Endlosschleifen
   und alles, was Position verändert; Letzteres regelt jede Komponente in
   ihrem eigenen reduced-motion-Block, weil Dokument-CSS nicht in die
   Shadow Roots hineinreicht. */
@media (prefers-reduced-motion: reduce) {
  site-preloader, cursor-glow { display: none !important; }
  html { scroll-behavior: auto; }
  .reveal { opacity: 1 !important; transform: none !important; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}
