/* ============================================================
   EGH Gebaeudeservice / 02 - BASIS
   Reset, Typografie, Bildsystem, Fokus, Auftritte.
   ============================================================ */

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

html {
  -webkit-text-size-adjust: 100%;
  background: var(--grund);
  /* Native Browser-Glaettung statt einer Bibliothek. Das ist
     die Entscheidung, die diese Seite am staerksten von einer
     Vorfuehrseite unterscheidet: Sie scrollt so, wie das Geraet
     scrollt, mit Impuls, mit Gummiband am Rand und ohne dass
     ein Skript den Takt vorgibt. */
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  font-family: var(--font-text);
  font-size: var(--t-body);
  line-height: var(--lead-body);
  color: var(--auf-grund);
  background: var(--grund);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
  overflow-x: clip;
}

h1, h2, h3, h4, p, figure, blockquote, ul, ol, dl { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
button, input, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }

/* --- Fokus -------------------------------------------------
   Sichtbar, im Markenton, mit Abstand zum Element. Wird nie
   entfernt: Ohne ihn ist die Seite mit der Tastatur nicht
   bedienbar, und das betrifft mehr Menschen, als man denkt. */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: var(--r-1);
}

.skip {
  position: fixed;
  top: 0; left: 50%;
  transform: translate(-50%, -110%);
  z-index: 200;
  background: var(--gold);
  color: var(--grund);
  padding: 0.8rem 1.4rem;
  font: 500 var(--t-sm)/1 var(--font-kopf);
  border-radius: 0 0 var(--r-1) var(--r-1);
  transition: transform var(--d-mittel) var(--e-aus);
}
.skip:focus-visible { transform: translate(-50%, 0); outline-offset: -4px; }

::selection { background: var(--gold); color: var(--gold); }

/* ============================================================
   TYPOGRAFIE
   ============================================================ */

.kopf {
  font-family: var(--font-kopf);
  font-weight: 700;
  line-height: var(--lead-kopf);
  letter-spacing: var(--track-xl);
  color: var(--auf-grund);
  text-wrap: balance;
  hyphens: auto;
}
.kopf--mega { font-size: var(--t-mega); letter-spacing: var(--track-mega); }
.kopf--xl   { font-size: var(--t-xl); }
.kopf--lg   { font-size: var(--t-lg); letter-spacing: var(--track-lg); line-height: 1.18; }
.kopf--md   { font-size: var(--t-md); letter-spacing: -0.01em; line-height: 1.25; }

/* Ein Wort in der Schlagzeile, das die Marke traegt. Nicht
   gefaerbt, sondern unterstrichen: eine zweite Textfarbe in
   einer Ueberschrift zerlegt den Satz in zwei Haelften. */
.strich {
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 92%;
  background-size: 100% 0.12em;
  padding-bottom: 0.04em;
}

/* Auszeichnung. Grotesk, Versalien, weite Laufweite, davor
   eine kurze Goldlinie, die beim Auftritt gezogen wird. */
.label {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  font-family: var(--font-kopf);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--akzent);
  line-height: 1;
}
.label::before {
  content: "";
  width: 1.75rem;
  height: 2px;
  background: var(--akzent-linie);
  transform-origin: left center;
}
@media (prefers-reduced-motion: no-preference) {
  html.js [data-auf] .label::before { transform: scaleX(0); }
  html.js [data-auf].ist-da .label::before {
    transform: scaleX(1);
    transition: transform 0.7s var(--e-aus) 0.15s;
  }
}

.lede {
  font-size: var(--t-lede);
  line-height: var(--lead-lede);
  color: var(--auf-grund);
  max-width: 38ch;
  text-wrap: pretty;
}

.fliess { max-width: var(--maxw-text); color: var(--auf-grund-2); text-wrap: pretty; }
.fliess p + p { margin-top: 1.1em; }

/* Zahlen in Tabellenziffern, damit eine Spalte von Preisen
   beim Aendern nicht flimmert. */
.zahl { font-family: var(--font-kopf); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }

/* ============================================================
   BILDER

   Keine Umfaerbung. Eine Reinigungsfirma verkauft Helligkeit
   und echte Farbe; ein entsaettigtes Foto wuerde das Gegenteil
   behaupten. Die Angleichung passiert beim Erzeugen der
   Dateien, nicht im Browser, damit kein Filter Rechenzeit
   kostet und kein Bild grau erscheint, bevor es geladen ist.
   ============================================================ */

.bild {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-2);
  background: color-mix(in srgb, var(--auf-grund) 6%, var(--flaeche));
}
.bild img { width: 100%; height: 100%; object-fit: cover; }

/* Beim Ueberfahren einer Karte zieht das Bild leicht an. Sehr
   wenig: es soll sich anfuehlen, nicht auffallen. */
@media (hover: hover) and (pointer: fine) {
  a:hover .bild img { transform: scale(1.03); }
  .bild img { transition: transform 0.7s var(--e-aus); }
}

.ar-4-3   { aspect-ratio: 4 / 3; }
.ar-4-5   { aspect-ratio: 4 / 5; }
.ar-1-1   { aspect-ratio: 1 / 1; }
.ar-16-9  { aspect-ratio: 16 / 9; }

/* ============================================================
   AUFTRITTE

   Ein Muster fuer die ganze Seite: Der Block faehrt zwoelf
   Pixel hoch und wird sichtbar. Mehr nicht. Gesetzt wird die
   Klasse von scripts/auftritt.js ueber einen
   IntersectionObserver, nicht ueber einen Scroll-Handler.

   Der Ausgangszustand haengt an html.js. Faellt JavaScript
   aus, faellt der Ausgangszustand mit weg und nicht der
   Inhalt.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  html.js [data-auf] { opacity: 0; transform: translate3d(0, 12px, 0); }
  html.js [data-auf].ist-da {
    opacity: 1;
    transform: none;
    transition: opacity var(--d-auftritt) var(--e-aus),
                transform var(--d-auftritt) var(--e-aus);
  }

  /* Gestaffelt. Der Index kommt aus dem Markup, nicht aus
     nth-child: So bleibt die Staffelung auch dann richtig,
     wenn der Filter Zeilen ausblendet. */
  html.js [data-auf].ist-da > [data-nach] {
    transition-delay: calc(var(--nach, 0) * 70ms);
  }
  html.js [data-auf] > [data-nach] { opacity: 0; transform: translate3d(0, 10px, 0); }
  html.js [data-auf].ist-da > [data-nach] {
    opacity: 1;
    transform: none;
    transition: opacity 0.55s var(--e-aus) calc(var(--nach, 0) * 70ms),
                transform 0.55s var(--e-aus) calc(var(--nach, 0) * 70ms);
  }
}

/* ============================================================
   FORTSCHRITT

   Ein zwei Pixel hoher Goldstrich am oberen Rand. Er laeuft
   ueber eine scrollgetriebene Animation, also ganz ohne
   JavaScript: kein Handler, kein Frame, keine Rechenzeit.
   Browser, die das nicht koennen, zeigen ihn einfach nicht.
   ============================================================ */
.fortschritt {
  position: fixed;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: var(--z-fort);
  pointer-events: none;
  background: var(--gold);
  transform-origin: left center;
  transform: scaleX(0);
}
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .fortschritt {
      animation: fortschritt linear both;
      animation-timeline: scroll(root block);
    }
  }
}
@keyframes fortschritt { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* Hilfsklassen */
.sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
