/* =============================================================
   Julian Litwinow. Freelance-Website.
   Aufbau: 1 Tokens  2 Basis  3 Bausteine  4 Sektionen  5 Bewegung
           5b dieselbe Bewegung fuer Browser ohne Zeitachsen
   Radien: genau ein Wert (--r: 2px). Bilder und Panels teilen ihn.
   Bewegung: CSS scroll-driven animations. Wo der Browser die kennt,
   laeuft kein Scroll-Listener mit; sonst fuehrt main.js sie nach und
   setzt dafuer die Klasse .bewegt (Abschnitt 5b).
   ============================================================= */

/* ---------- 1 Tokens ---------------------------------------- */

:root {
  --paper: #FAFAF7;
  --ink:   #0D0D0F;

  /* Helles Grundthema */
  --bg:          #FAFAF7;
  --fg:          #0D0D0F;
  --dim:         #5F5F5A;
  --rule:        rgba(13, 13, 15, .14);
  --panel:       #FFFFFF;
  --panel-rule:  rgba(13, 13, 15, .11);
  --panel-soft:  rgba(13, 13, 15, .035);
  --accent:      #C9330C;
  --accent-fg:   #FFFFFF;
  --accent-soft: rgba(201, 51, 12, .09);
  --shadow:      0 1px 2px rgba(13,13,15,.05), 0 12px 36px rgba(13,13,15,.07);

  --r: 2px;
  --nav-h: 68px;
  --gutter: clamp(1.25rem, 5vw, 5rem);
  --maxw: 1360px;

  --sans: "Geist", ui-sans-serif, system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "Geist Mono", ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;

  --ease: cubic-bezier(.16, 1, .3, 1);
}

/* Invertiertes Kapitel: genau ein bewusster Themenwechsel auf der Seite. */
.chapter {
  --bg:          #0D0D0F;
  --fg:          #F3F2ED;
  --dim:         #97968E;
  --rule:        rgba(243, 242, 237, .17);
  --panel:       #17171A;
  --panel-rule:  rgba(243, 242, 237, .13);
  --panel-soft:  rgba(243, 242, 237, .05);
  --accent:      #FF6A3D;
  --accent-fg:   #1A0800;
  --accent-soft: rgba(255, 106, 61, .13);
  --shadow:      0 1px 2px rgba(0,0,0,.5), 0 18px 50px rgba(0,0,0,.45);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:          #0D0D0F;
    --fg:          #F3F2ED;
    --dim:         #97968E;
    --rule:        rgba(243, 242, 237, .17);
    --panel:       #17171A;
    --panel-rule:  rgba(243, 242, 237, .13);
    --panel-soft:  rgba(243, 242, 237, .05);
    --accent:      #FF6A3D;
    --accent-fg:   #1A0800;
    --accent-soft: rgba(255, 106, 61, .13);
    --shadow:      0 1px 2px rgba(0,0,0,.5), 0 18px 50px rgba(0,0,0,.45);
  }
  .chapter {
    --bg:          #FAFAF7;
    --fg:          #0D0D0F;
    --dim:         #5F5F5A;
    --rule:        rgba(13, 13, 15, .14);
    --panel:       #FFFFFF;
    --panel-rule:  rgba(13, 13, 15, .11);
    --panel-soft:  rgba(13, 13, 15, .035);
    --accent:      #C9330C;
    --accent-fg:   #FFFFFF;
    --accent-soft: rgba(201, 51, 12, .09);
    --shadow:      0 1px 2px rgba(13,13,15,.05), 0 12px 36px rgba(13,13,15,.07);
  }
}

/* ---------- 2 Basis ----------------------------------------- */

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

/* Muss vor allen Bausteinen stehen: mehrere Zustaende der Demos werden
   ueber [hidden] geschaltet, und ein display aus einer Klasse gewinnt
   sonst gegen die Vorgabe des Browsers. */
[hidden] { display: none !important; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 1rem);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: clamp(1rem, .96rem + .2vw, 1.0625rem);
  line-height: 1.62;
  font-weight: 400;
  letter-spacing: -.005em;
  -webkit-font-smoothing: antialiased;
}
/* Kein overflow-x: hidden auf body. Das macht den Body zum Scrollcontainer
   und nimmt allen sticky-Elementen darin die Wirkung. Waagerechter Ueberlauf
   wird stattdessen dort begrenzt, wo er entsteht: in .pan__stage. */

h1, h2, h3 {
  margin: 0;
  font-weight: 600;
  letter-spacing: -.035em;
  line-height: 1.04;
  text-wrap: balance;
}

h2 { font-size: clamp(2rem, 1.15rem + 3.6vw, 3.9rem); }
h3 { font-size: clamp(1.125rem, 1.02rem + .45vw, 1.4rem); letter-spacing: -.02em; line-height: 1.2; }

p { margin: 0; }
img { display: block; max-width: 100%; height: auto; }

a { color: inherit; }
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--r);
}

::selection { background: var(--accent); color: var(--accent-fg); }

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.mono {
  font-family: var(--mono);
  font-size: .6875rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: 500;
}

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

.skip {
  position: absolute; left: 1rem; top: -4rem; z-index: 200;
  background: var(--fg); color: var(--bg);
  padding: .7rem 1.1rem; border-radius: var(--r);
  text-decoration: none; font-weight: 500;
  transition: top .2s var(--ease);
}
.skip:focus { top: 1rem; }

.eyebrow {
  color: var(--accent);
  margin-bottom: 1.1rem;
}
/* Der Strich davor gehoert zur Zeile, nicht zur Bewegung: ohne
   scroll-driven animations steht er einfach in voller Laenge da. */
.eyebrow::before {
  content: ""; display: inline-block;
  width: 2.25rem; height: 1px; margin-right: .7rem;
  vertical-align: middle;
  background: currentColor;
  transform-origin: left center;
}

.tag {
  display: inline-block;
  padding: .28rem .5rem;
  border: 1px solid var(--accent);
  color: var(--accent);
  border-radius: var(--r);
  font-size: .625rem;
  line-height: 1;
}

/* ---------- 3 Bausteine ------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .5rem;
  padding: .95rem 1.5rem;
  border: 1px solid transparent;
  border-radius: var(--r);
  font: inherit;
  font-weight: 500;
  font-size: .9375rem;
  letter-spacing: -.01em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .25s var(--ease), color .25s var(--ease),
              border-color .25s var(--ease), transform .12s var(--ease);
}
.btn--primary { background: var(--accent); color: var(--accent-fg); }
.btn--primary:hover { background: color-mix(in srgb, var(--accent) 84%, var(--fg)); }
.btn--ghost { border-color: var(--rule); color: var(--fg); background: transparent; }
.btn--ghost:hover { border-color: var(--fg); background: var(--panel-soft); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .38; cursor: not-allowed; }
.btn:disabled:active { transform: none; }
.btn--sm { padding: .6rem 1rem; font-size: .875rem; }
.btn--wide { width: 100%; padding-block: 1.05rem; }

.linkish {
  background: none; border: 0; padding: 0;
  font: inherit; font-size: .875rem;
  color: var(--dim);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.linkish:hover { color: var(--fg); }

/* Panel: gemeinsame Huelle aller drei bedienbaren Demos */
.panel {
  background: var(--panel);
  border: 1px solid var(--panel-rule);
  border-radius: var(--r);
  box-shadow: var(--shadow);
  overflow: hidden;
}
/* Fensterleiste im Stil eines Programmfensters. Das ist keine Zierde:
   ein Besucher hat die Terminbuchung fuer eine echte Buchung gehalten.
   Drei Knoepfe, ein Titel und das Wort "Beispiel" sagen auf einen Blick,
   dass hier eine Vorfuehrung laeuft und nichts verschickt wird. */
.panel__bar {
  position: relative;
  display: flex; align-items: center; gap: .75rem;
  padding: .7rem 1.1rem;
  border-bottom: 1px solid var(--panel-rule);
  background: var(--panel-soft);
}
.panel__lights { display: flex; gap: 6px; flex: none; }
.panel__lights span {
  width: 11px; height: 11px; border-radius: 50%; display: block;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .16);
}
.panel__lights span:nth-child(1) { background: #FF5F57; }
.panel__lights span:nth-child(2) { background: #FEBC2E; }
.panel__lights span:nth-child(3) { background: #28C840; }

/* Mittig wie in einem Fenstertitel. Absolut, damit die Knoepfe links und
   die Kennzeichnung rechts die Mitte nicht verschieben. */
.panel__title {
  position: absolute; left: 50%; transform: translateX(-50%);
  font-size: .8125rem; font-weight: 500; letter-spacing: -.01em;
  color: var(--dim);
  white-space: nowrap;
  pointer-events: none;
}
.panel__title .mono { font-size: .6875rem; color: var(--dim); letter-spacing: .06em; }
.panel__demo { margin-left: auto; flex: none; }

/* Der Satz unter dem Fenster. Ohne ihn bleibt "Beispiel" eine Vokabel. */
.panel__note {
  display: flex; align-items: baseline; gap: .5rem;
  margin-top: .85rem;
  color: var(--dim); font-size: .8125rem;
}
.panel__note i { color: var(--accent); font-size: .9375rem; flex: none; }

.ticks { list-style: none; margin: 1.75rem 0 0; padding: 0; display: grid; gap: .7rem; }
.ticks li { display: flex; gap: .65rem; align-items: baseline; color: var(--dim); font-size: .9375rem; }
.ticks i { color: var(--accent); font-size: 1rem; }

/* ---------- 4 Sektionen ------------------------------------- */

/* 4.1 Navigation: eine Zeile, 68px */
.nav {
  position: sticky; top: 0; z-index: 100;
  background: var(--bg);
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid var(--rule);
}
@supports not (backdrop-filter: blur(1px)) { .nav { background: var(--bg); } }

.nav__inner {
  height: var(--nav-h);
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex; align-items: center; gap: 2rem;
}
.nav__brand { display: flex; align-items: center; gap: .6rem; text-decoration: none; margin-right: auto; }
.nav__mark { width: 27px; height: 27px; display: block; flex: none; }
/* Das Zeichen steht frei, ohne Kachel: eine Linie für das J, der Kopfstrich
   in der Akzentfarbe. Beide nehmen die Farben des Themas an, damit es hell
   wie dunkel dieselbe Stärke behält. */
.nav__markJ   { stroke: var(--fg); }
.nav__markBar { stroke: var(--accent); }
.nav__name { font-weight: 500; font-size: .9375rem; letter-spacing: -.02em; }
.nav__links { display: flex; gap: 1.85rem; }
.nav__links a {
  text-decoration: none; font-size: .9375rem; color: var(--dim);
  transition: color .2s var(--ease);
}
.nav__links a:hover { color: var(--fg); }
.nav__cta { padding: .6rem 1.05rem; font-size: .875rem; }

/* Lesefortschritt. Liegt auf der unteren Kante der Leiste, damit er keine
   eigene Zeile braucht. Ohne scroll() bleibt er unsichtbar. */
.progress {
  position: absolute; left: 0; bottom: -1px;
  height: 2px; width: 100%;
  background: var(--accent);
  transform: scaleX(0); transform-origin: left;
}

.nav__burger {
  display: none;
  width: 40px; height: 40px;
  background: none; border: 1px solid var(--rule); border-radius: var(--r);
  cursor: pointer;
  padding: 0;
  place-items: center;
  gap: 5px;
}
.nav__burger span { display: block; width: 16px; height: 1.5px; background: var(--fg); }
.nav__mobile { display: none; }

/* 4.2 Hero */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-top: 2.5rem;
  padding-bottom: clamp(3rem, 7vw, 6rem);
  min-height: calc(100dvh - var(--nav-h));
  display: flex; align-items: center;
}

/* Hintergrund: gerechnet, kein Bild. Drei Lagen, damit der Kopf nicht leer
   wirkt, ohne dass etwas vom Text ablenkt: ein Raster als Grundton, ein
   Lichtschein in Akzentfarbe hinter dem Fenster, ein zweiter, kuehler
   Schein unten links als Gegengewicht. */
.hero__bg {
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none;
  overflow: hidden;
}
.hero__bg::before {
  content: "";
  position: absolute; inset: -15%;
  background-image:
    linear-gradient(to right,  var(--rule) 1px, transparent 1px),
    linear-gradient(to bottom, var(--rule) 1px, transparent 1px);
  background-size: 78px 78px;
  opacity: .6;
  /* Ohne Maske laeuft das Raster in die Kanten und sieht nach Millimeterpapier
     aus. Die Maske laesst es dort stehen, wo nichts gelesen wird. */
  -webkit-mask-image: radial-gradient(120% 90% at 74% 14%, #000 0%, transparent 70%);
          mask-image: radial-gradient(120% 90% at 74% 14%, #000 0%, transparent 70%);
}
.hero__glow {
  position: absolute;
  right: -14%; top: -34%;
  width: min(940px, 92vw); aspect-ratio: 1;
  background: radial-gradient(circle at center,
              color-mix(in srgb, var(--accent) 26%, transparent) 0%,
              transparent 62%);
  opacity: .55;
}
.hero__glow--low {
  right: auto; top: auto;
  left: -22%; bottom: -46%;
  width: min(760px, 80vw);
  background: radial-gradient(circle at center,
              color-mix(in srgb, var(--fg) 12%, transparent) 0%,
              transparent 64%);
  opacity: .5;
}
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr);
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}
/* Der Schriftgrad ist an die Breite der Textspalte gerechnet, damit die
   Zeile "Websites und Systeme," bis hinunter zu 1000 px eine Zeile bleibt. */
.hero__title {
  font-size: clamp(2.2rem, 4.6vw, 3.85rem);
  letter-spacing: -.045em;
}
.hero__title .line { display: block; overflow: hidden; padding-bottom: .06em; }
.hero__title .line > span { display: block; }
/* Betonung ueber Farbe, nicht ueber eine zweite Schrift. Geist liefert
   keine echte Kursive, eine berechnete Schraege sieht billig aus. */
.hero__title em { font-style: normal; color: var(--accent); }
.hero__sub {
  margin-top: 1.6rem;
  max-width: 44ch;
  color: var(--dim);
  font-size: clamp(1.0625rem, 1rem + .35vw, 1.25rem);
}
.hero__actions { margin-top: 2.25rem; display: flex; flex-wrap: wrap; gap: .75rem; }

/* Buchungs-Demo */
.booking__days {
  display: grid; grid-template-columns: repeat(5, 1fr);
  border-bottom: 1px solid var(--panel-rule);
}
.booking__day {
  background: none; border: 0; border-right: 1px solid var(--panel-rule);
  padding: .85rem .4rem; cursor: pointer; font: inherit; color: var(--dim);
  display: grid; gap: .15rem; text-align: center;
  transition: background-color .2s var(--ease), color .2s var(--ease);
}
.booking__day:last-child { border-right: 0; }
.booking__day span { display: block; }
.booking__day .d { font-family: var(--mono); font-size: .625rem; letter-spacing: .1em; text-transform: uppercase; }
.booking__day .n { font-size: 1.0625rem; font-weight: 500; letter-spacing: -.02em; }
.booking__day:hover { background: var(--panel-soft); color: var(--fg); }
.booking__day[aria-selected="true"] { background: var(--fg); color: var(--panel); }

.booking__body { min-height: 172px; display: grid; }
.booking__slots {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: .5rem; padding: 1.1rem;
  align-content: start;
}
.booking__slot {
  padding: .6rem .2rem;
  border: 1px solid var(--panel-rule); border-radius: var(--r);
  background: none; color: var(--fg);
  font-family: var(--mono); font-size: .75rem; letter-spacing: .04em;
  cursor: pointer;
  transition: border-color .2s var(--ease), background-color .2s var(--ease), color .2s var(--ease);
}
.booking__slot:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.booking__slot[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
.booking__slot:disabled {
  color: var(--dim); cursor: not-allowed;
  background: repeating-linear-gradient(-45deg, transparent 0 5px, var(--panel-soft) 5px 10px);
}

.booking__done { padding: 2rem 1.4rem; text-align: center; align-content: center; display: grid; gap: .5rem; justify-items: center; }
.booking__done i { font-size: 2rem; color: var(--accent); }
.booking__doneText { font-size: .9375rem; }

.booking__foot {
  display: flex; align-items: center; gap: 1rem;
  padding: .9rem 1.1rem;
  border-top: 1px solid var(--panel-rule);
  background: var(--panel-soft);
}
.booking__sel { color: var(--dim); font-size: .625rem; margin-right: auto; letter-spacing: .06em; }

/* 4.3 Zoom auf die Betreiberansicht */
.zoom { padding-block: clamp(4.5rem, 10vw, 9rem); }
/* Die Spalte wird auf 1fr festgenagelt. Ohne das richtet sie sich nach der
   Mindestbreite des Kursplans, und das Fenster wird auf dem Handy zu breit. */
.zoom__stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: clamp(2rem, 4vw, 3.5rem);
  padding-inline: var(--gutter);
}
.zoom__head { max-width: 46ch; text-align: center; }
.zoom__head p { margin-top: 1.1rem; color: var(--dim); }
.zoom__frame { width: min(1180px, 100%); max-width: 100%; }

/* Kursplan: die Ansicht, auf der der Betreiber arbeitet */
.week__scroll { overflow-x: auto; }
.week__grid {
  display: grid;
  grid-template-columns: 4.5rem repeat(5, minmax(0, 1fr));
  border-bottom: 1px solid var(--panel-rule);
  min-width: 34rem;
}
.week__head, .week__time {
  font-family: var(--mono); font-size: .625rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim);
  display: grid; place-items: center;
  padding: .7rem .3rem;
  border-bottom: 1px solid var(--panel-rule);
}
.week__time { border-bottom: 0; border-right: 1px solid var(--panel-rule); }
.week__cell {
  border: 0; border-right: 1px solid var(--panel-rule);
  background: none; color: var(--fg); font: inherit;
  padding: .8rem .55rem; min-height: 4.25rem;
  display: grid; align-content: start; gap: .3rem; text-align: left;
  cursor: pointer;
  transition: background-color .2s var(--ease);
}
.week__cell:last-child { border-right: 0; }
.week__cell:hover { background: var(--panel-soft); }
.week__cell[aria-pressed="true"] { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }
.week__cell:disabled { cursor: default; background: repeating-linear-gradient(-45deg, transparent 0 6px, var(--panel-soft) 6px 12px); }
.week__name { font-size: .8125rem; font-weight: 500; letter-spacing: -.01em; }
.week__count { font-family: var(--mono); font-size: .6875rem; color: var(--dim); }
.week__cell--full .week__count,
.week__cell--wait .week__count { color: var(--accent); font-weight: 500; }

.week__detail {
  display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1.25rem;
  padding: .9rem 1.1rem;
  background: var(--panel-soft);
  min-height: 4rem;
}
.week__hint { color: var(--dim); font-size: .875rem; }
.week__info { margin-right: auto; }
.week__info strong { font-size: .9375rem; font-weight: 500; }
.week__info span { display: block; color: var(--dim); font-size: .8125rem; }
.week__acts { display: flex; gap: .5rem; }

/* 4.4 Kapitelrahmen */
.chapter {
  position: relative;
  background: var(--bg);
  color: var(--fg);
  border-radius: 0;
}

/* 4.5 Leistungen: alle fuenf auf einem Bildschirm, ohne Scrollaufwand */
.services { padding-block: clamp(4.5rem, 10vw, 9rem); }
.services__head { margin-bottom: clamp(2rem, 4vw, 3.5rem); }
.services__h { max-width: 16ch; }
.services__grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 1px;
  background: var(--rule);
  border-block: 1px solid var(--rule);
}
.card {
  background: var(--bg);
  padding: clamp(1.5rem, 2.4vw, 2.25rem);
  display: flex; flex-direction: column; gap: .75rem;
}
.card__i { font-size: 1.5rem; color: var(--accent); margin-bottom: .5rem; }
.card p { color: var(--dim); font-size: .9375rem; }
.card__meta { margin-top: auto; padding-top: 1.5rem; color: var(--accent); font-size: .625rem; }
.card--accent { background: var(--accent-soft); }
.services__grid .card:nth-child(1) { --n: 0; }
.services__grid .card:nth-child(2) { --n: 1; }
.services__grid .card:nth-child(3) { --n: 2; }
.services__grid .card:nth-child(4) { --n: 3; }
.services__grid .card:nth-child(5) { --n: 4; }

/* 4.6 Rechnung */
.split { padding-block: clamp(4.5rem, 10vw, 9rem); }
.split__grid {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: center;
}
.split__copy h2 { max-width: 12ch; }
.split__copy p { margin-top: 1.4rem; color: var(--dim); max-width: 46ch; }

.invoice__add {
  display: flex; gap: .5rem; padding: 1.1rem;
  border-bottom: 1px solid var(--panel-rule);
}
.invoice__add select { flex: 1; min-width: 0; }

select, input[type="text"], input[type="email"], textarea {
  font: inherit; font-size: .9375rem;
  color: var(--fg);
  background: var(--panel);
  border: 1px solid var(--panel-rule);
  border-radius: var(--r);
  padding: .7rem .8rem;
  width: 100%;
}
textarea { resize: vertical; }
::placeholder { color: var(--dim); opacity: 1; }

.invoice__rows { display: grid; }
.invoice__row {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  align-items: center;
  gap: .9rem;
  padding: .8rem 1.1rem;
  border-bottom: 1px solid var(--panel-rule);
}
.invoice__name { font-size: .9375rem; letter-spacing: -.01em; }
.invoice__unit { display: block; color: var(--dim); font-size: .75rem; }
.invoice__qty { display: flex; align-items: center; gap: .1rem; }
.invoice__qty button {
  width: 26px; height: 26px;
  border: 1px solid var(--panel-rule); background: none; color: var(--fg);
  border-radius: var(--r); cursor: pointer; font: inherit; line-height: 1;
  display: grid; place-items: center;
}
.invoice__qty button:hover { border-color: var(--accent); color: var(--accent); }
.invoice__qty output { width: 2.1rem; text-align: center; font-family: var(--mono); font-size: .8125rem; }
.invoice__line { font-family: var(--mono); font-size: .8125rem; min-width: 5.5rem; text-align: right; }
.invoice__del {
  background: none; border: 0; color: var(--dim); cursor: pointer;
  font-size: 1rem; line-height: 1; padding: .25rem;
}
.invoice__del:hover { color: var(--accent); }

.invoice__empty { padding: 2rem 1.1rem; text-align: center; color: var(--dim); font-size: .875rem; }

.invoice__sum { margin: 0; padding: 1.1rem; display: grid; gap: .45rem; background: var(--panel-soft); }
.invoice__sum > div { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.invoice__sum dt { color: var(--dim); font-size: .875rem; }
.invoice__sum dd { margin: 0; font-size: .8125rem; }
.invoice__total { padding-top: .55rem; border-top: 1px solid var(--panel-rule); }
.invoice__total dt { color: var(--fg); font-weight: 500; font-size: 1rem; }
.invoice__total dd { font-size: 1.0625rem; font-weight: 500; color: var(--accent); }

/* 4.7 Warenwirtschaft */
.wws { padding-block: clamp(4.5rem, 10vw, 9rem); }
.wws__h { max-width: 14ch; }
.wws__lead { margin: 1.4rem 0 clamp(2rem, 4vw, 3rem); color: var(--dim); max-width: 52ch; }

.stock__alert {
  display: flex; gap: .7rem; align-items: center;
  padding: .85rem 1.1rem;
  background: var(--accent-soft);
  border-bottom: 1px solid var(--panel-rule);
  color: var(--accent);
  font-size: .875rem;
}
.stock__alert i { font-size: 1.15rem; flex: none; }

.stock__scroll { overflow-x: auto; }
.stock__table { width: 100%; border-collapse: collapse; min-width: 21rem; }
.stock__table th, .stock__table td {
  padding: .85rem 1.1rem; text-align: left;
  border-bottom: 1px solid var(--panel-rule);
}
.stock__table th {
  font-family: var(--mono); font-size: .625rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim); font-weight: 500;
}
.stock__table .num { text-align: right; }
.stock__table td.num { font-family: var(--mono); font-size: .875rem; }
.stock__table tr:last-child td { border-bottom: 0; }
.stock__name { font-size: .9375rem; letter-spacing: -.01em; }
.stock__sku { display: block; color: var(--dim); font-family: var(--mono); font-size: .625rem; letter-spacing: .06em; }
.stock__row--low td.num:first-of-type { color: var(--accent); font-weight: 500; }
.stock__act { text-align: right; }

.stock__foot {
  display: flex; align-items: center; gap: 1rem;
  padding: .9rem 1.1rem; border-top: 1px solid var(--panel-rule);
  background: var(--panel-soft);
}
.stock__foot .mono { color: var(--dim); font-size: .625rem; margin-right: auto; letter-spacing: .06em; }

/* 4.8 Ablauf */
.flow { padding-block: clamp(5rem, 11vw, 10rem); }
.flow__h { max-width: 16ch; margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.flow__list {
  list-style: none; margin: 0; padding: 0;
  position: relative;
  display: grid; gap: clamp(2rem, 4vw, 3.25rem);
}
.flow__list::before {
  content: ""; position: absolute;
  left: 15px; top: .6rem; bottom: .6rem; width: 1px;
  background: var(--rule);
}
.flow__list::after {
  content: ""; position: absolute;
  left: 15px; top: .6rem; width: 1px; height: calc(100% - 1.2rem);
  background: var(--accent);
  transform-origin: top;
  transform: scaleY(0);
}
.flow__step {
  display: grid; grid-template-columns: 34px minmax(0, 1fr);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  position: relative;
}
.flow__num {
  color: var(--accent);
  background: var(--bg);
  padding-block: .25rem;
  font-size: .6875rem;
  z-index: 1;
}
.flow__step p { margin-top: .7rem; color: var(--dim); max-width: 52ch; }

/* 4.9 Arbeiten */
.work { padding-block: clamp(4.5rem, 10vw, 9rem); }
.work__h { margin-bottom: clamp(2rem, 4vw, 3rem); }
.work__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 3rem);
}
.work__item { margin: 0; }

/* Die Arbeiten stecken im selben Fensterrahmen wie die Vorfuehrungen weiter
   oben. Nur die Leiste sagt hier nicht "Beispiel", sondern die Adresse:
   das ist eine gebaute Seite, kein Muster. */
/* Beim Zeigen nur der Schatten. Ein transform waere hier wirkungslos: das
   Fenster haengt an einer Scroll-Bewegung, und die gewinnt gegen jede
   normale Regel. */
.work__panel { transition: box-shadow .5s var(--ease); }
.work__item:hover .work__panel { box-shadow: 0 2px 4px rgba(13,13,15,.06), 0 22px 60px rgba(13,13,15,.13); }
.work__panel .panel__title { color: var(--dim); }

.work__item img {
  display: block;
  width: 100%; object-fit: cover;
  aspect-ratio: 16 / 9;
  filter: grayscale(1) contrast(1.04);
  transition: filter .5s var(--ease);
}
.work__item:hover img { filter: grayscale(0) contrast(1); }
.work__item figcaption { padding-top: 1.1rem; display: grid; gap: .5rem; justify-items: start; }
.work__item figcaption p { color: var(--dim); font-size: .875rem; }

/* Arbeit ohne Bild: eine Flaeche statt einer Erfindung. Sie hat dieselben
   Masse wie ein Bild, damit das Raster nicht springt. */
.work__blind {
  aspect-ratio: 16 / 9;
  background:
    radial-gradient(120% 90% at 50% 0%, var(--panel-soft), transparent 70%),
    repeating-linear-gradient(45deg, var(--panel-soft) 0 1px, transparent 1px 9px);
  display: grid; place-content: center; justify-items: center; gap: .6rem;
  color: var(--dim);
}
.work__blind i { font-size: 1.6rem; }
.work__blind p { margin: 0; font-size: .6875rem; letter-spacing: .09em; text-transform: uppercase; }

/* Der Titel ist der Link. Der Pfeil sitzt in der Zeile und wandert beim
   Zeigen mit, damit klar ist, dass die Seite wirklich aufgeht. */
.work__link {
  color: inherit; text-decoration: none;
  display: inline-flex; align-items: center; gap: .45rem;
}
.work__link span {
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-size: 0% 1px;
  background-position: 0 100%;
  transition: background-size .45s var(--ease);
}
.work__link i { font-size: .8em; color: var(--accent); transition: transform .35s var(--ease); }
.work__link:hover span, .work__link:focus-visible span { background-size: 100% 1px; }
.work__link:hover i, .work__link:focus-visible i { transform: translate(2px, -2px); }

/* 4.10 Zusagen */
.stance { padding-block: clamp(4.5rem, 10vw, 9rem); border-top: 1px solid var(--rule); }
.stance__grid {
  display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
  gap: clamp(2rem, 5vw, 5rem);
}
.stance__h { align-self: start; position: sticky; top: calc(var(--nav-h) + 3rem); }
.stance__items { display: grid; gap: clamp(2rem, 3.5vw, 3rem); }
.stance__item p { margin-top: .65rem; color: var(--dim); max-width: 50ch; }

/* 4.11 Pakete */
.plans { padding-block: clamp(4.5rem, 10vw, 9rem); }
.plans__h { margin-bottom: 1.4rem; max-width: 18ch; }
.plans__lead { margin-bottom: clamp(2rem, 4vw, 3rem); color: var(--dim); max-width: 54ch; }
.plans__grid {
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  overflow: hidden;
}
.plan {
  background: var(--bg);
  padding: clamp(1.75rem, 3vw, 2.75rem);
  display: flex; flex-direction: column; align-items: start; gap: .8rem;
}
.plan--lead { grid-row: 1 / span 2; }
.plan__price {
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.4rem);
  font-weight: 600; letter-spacing: -.035em;
  line-height: 1;
}
.plan p:not(.plan__price) { color: var(--dim); font-size: .9375rem; max-width: 40ch; }
/* Die Zeile sitzt unten am Rand der Kachel, damit alle drei Kacheln unten
   dieselbe Kante haben, egal wie lang der Text darueber ist. */
.plan p.plan__meta { margin-top: auto; padding-top: 1.5rem; color: var(--accent); font-size: .625rem; }
.plan .btn { margin-top: 1.25rem; }

/* 4.12 Anfrage */
.contact { padding-block: clamp(5rem, 11vw, 10rem); border-top: 1px solid var(--rule); }
.contact__grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .95fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
}
.contact__copy h2 { max-width: 13ch; }
.contact__copy p { margin-top: 1.4rem; color: var(--dim); max-width: 44ch; }
.contact__direct { margin-top: 2rem; }
.contact__direct a {
  font-size: 1.0625rem; color: var(--accent);
  text-decoration: underline; text-underline-offset: 4px;
}

.form { display: grid; gap: 1.25rem; }
/* Die Falle für Maschinen. Nicht display:none — das überspringen manche
   Programme absichtlich. So steht das Feld im Baum, ist aber für Augen
   und Tastatur nicht da. */
.falle {
  position: absolute; left: -9999px;
  width: 1px; height: 1px; overflow: hidden;
}
.field { display: grid; gap: .45rem; }
.field label { font-size: .875rem; font-weight: 500; }
.field__help { color: var(--dim); font-size: .8125rem; }
.field__err { color: var(--accent); font-size: .8125rem; font-weight: 500; }
.field[data-invalid] input, .field[data-invalid] textarea { border-color: var(--accent); }
.form__note { min-height: 1.4rem; font-size: .875rem; color: var(--dim); }
.form__note[data-ok] { color: var(--accent); font-weight: 500; }

/* 4.13 Fuss */
.foot { border-top: 1px solid var(--rule); padding-block: 2.5rem; }
.foot__inner { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 2rem; }
.foot__brand { font-weight: 500; letter-spacing: -.02em; margin-right: auto; }
.foot__links { display: flex; gap: 1.5rem; }
.foot__links a { color: var(--dim); text-decoration: none; font-size: .875rem; }
.foot__links a:hover { color: var(--fg); }
.foot__copy { color: var(--dim); font-size: .625rem; }

/* Rechtsseiten */
.legal { padding-block: clamp(3rem, 7vw, 6rem); max-width: 68ch; }
.legal h1 { font-size: clamp(2rem, 1.4rem + 2.4vw, 3rem); margin-bottom: 2rem; }
.legal h2 { font-size: clamp(1.15rem, 1rem + .7vw, 1.5rem); margin-top: 2.75rem; margin-bottom: .8rem; }
.legal p, .legal li { color: var(--dim); }
.legal p + p { margin-top: .9rem; }
.legal ul { margin: .9rem 0 0; padding-left: 1.2rem; display: grid; gap: .4rem; }
.legal a { color: var(--accent); }
.legal .todo {
  display: block; margin-top: 2rem; padding: 1rem 1.15rem;
  border: 1px solid var(--accent); border-radius: var(--r);
  color: var(--accent); font-size: .875rem;
}
.legal__back { display: inline-block; margin-top: 3rem; color: var(--dim); font-size: .875rem; }

/* 4.14 Zaehler fuer versetzte Eintritte.
   Steht ausserhalb des Bewegungsblocks: eine Zahl bewegt nichts, sie wird
   nur dort gelesen, wo scroll-driven animations laufen.

   Die Vorgabe --n: 0 steht bewusst zuerst und gilt fuer alles. Fehlt sie,
   hat ein Eintrag ohne eigene Zahl kein --n, dann wird die Rechnung in
   animation-range ungueltig, der Bereich faellt auf die volle Zeitachse
   zurueck, und das Element bleibt bei halber Deckkraft stehen. Da die
   Listen im Admin gepflegt werden, darf ein sechster Eintrag nicht
   halb durchsichtig auf der Seite landen. */
.flow__step, .plan, .stance__item, .work__item, .ticks li,
.form .field, .services__grid .card { --n: 0; }

/* Der Absendeknopf kommt nach den vier Feldern, also Zaehler 4. */
.form .btn { --n: 4; }

.flow__step:nth-child(2), .plan:nth-child(2), .stance__item:nth-child(2),
.work__item:nth-child(2), .ticks li:nth-child(2), .form .field:nth-child(2) { --n: 1; }
.flow__step:nth-child(3), .plan:nth-child(3), .stance__item:nth-child(3),
.work__item:nth-child(3), .ticks li:nth-child(3), .form .field:nth-child(3) { --n: 2; }
.flow__step:nth-child(4), .plan:nth-child(4), .stance__item:nth-child(4),
.work__item:nth-child(4), .ticks li:nth-child(4), .form .field:nth-child(4) { --n: 3; }
.flow__step:nth-child(5), .plan:nth-child(5), .stance__item:nth-child(5),
.work__item:nth-child(5), .ticks li:nth-child(5) { --n: 4; }
.flow__step:nth-child(6), .plan:nth-child(6), .stance__item:nth-child(6),
.work__item:nth-child(6), .ticks li:nth-child(6) { --n: 5; }
.flow__step:nth-child(7), .plan:nth-child(7), .stance__item:nth-child(7),
.work__item:nth-child(7), .ticks li:nth-child(7) { --n: 6; }
.flow__step:nth-child(8), .plan:nth-child(8), .stance__item:nth-child(8),
.work__item:nth-child(8), .ticks li:nth-child(8) { --n: 7; }

/* ---------- 5 Bewegung -------------------------------------- */
/* Alles hierunter ist Zugabe. Ohne Unterstuetzung oder bei
   prefers-reduced-motion bleibt die Seite exakt so, wie sie oben steht. */

@media (prefers-reduced-motion: no-preference) {

  @supports (animation-timeline: view()) {

    /* Eintritt: hebt die Reihenfolge hervor, in der gelesen werden soll */
    .reveal {
      animation: reveal linear both;
      animation-timeline: view();
      animation-range: entry 8% cover 32%;
    }
    @keyframes reveal {
      from { opacity: 0; transform: translateY(26px); }
      to   { opacity: 1; transform: none; }
    }

    /* Ueberschriften kommen eine Spur weiter und eine Spur spaeter als der
       Fliesstext darunter. Das legt die Lesereihenfolge fest, ohne dass
       jemand darueber nachdenken muss. */
    .rise {
      animation: riseIn linear both;
      animation-timeline: view();
      animation-range: entry 6% cover 36%;
    }
    @keyframes riseIn {
      from { opacity: 0; transform: translateY(38px) scale(.985); }
      to   { opacity: 1; transform: none; }
    }

    /* Lesefortschritt ueber das ganze Dokument */
    @supports (animation-timeline: scroll()) {
      .progress {
        animation: progress linear both;
        animation-timeline: scroll(root block);
      }
      @keyframes progress { to { transform: scaleX(1); } }

      /* Die Leiste bekommt erst Gewicht, wenn wirklich etwas unter ihr liegt */
      .nav {
        animation: navLift linear both;
        animation-timeline: scroll(root block);
        animation-range: 0 140px;
      }
      @keyframes navLift {
        from { box-shadow: 0 0 0 rgba(0,0,0,0); }
        to   { box-shadow: 0 10px 30px rgba(13,13,15,.07); }
      }
    }

    /* Hero-Hintergrund: zieht langsamer weg als der Text davor. Das ist der
       einzige Ort mit Parallaxe auf der Seite, deshalb faellt er auf. */
    .hero { view-timeline-name: --hero; }
    .hero__bg {
      animation: heroDrift linear both;
      animation-timeline: --hero;
      animation-range: entry 0% exit 100%;
      will-change: transform;
    }
    @keyframes heroDrift {
      from { transform: translate3d(0, -2%, 0) scale(1.06); }
      to   { transform: translate3d(0, 9%, 0) scale(1.06); }
    }
    /* Der Lichtschein atmet mit dem Scrollen, sonst wirkt die Flaeche tot. */
    .hero__glow {
      animation: glowShift linear both;
      animation-timeline: --hero;
      animation-range: entry 0% exit 100%;
    }
    @keyframes glowShift {
      from { opacity: .62; transform: translate3d(0, 0, 0) scale(1); }
      to   { opacity: .18; transform: translate3d(-4%, 8%, 0) scale(1.16); }
    }

    /* Hero: Zeilen fahren beim Laden von unten ein */
    .hero__title .line > span {
      animation: lineUp .95s var(--ease) both;
    }
    .hero__title .line:nth-child(2) > span { animation-delay: .09s; }
    .hero__sub, .hero__actions, .hero__demo {
      animation: fadeUp .8s var(--ease) both;
    }
    .hero__sub { animation-delay: .2s; }
    .hero__actions { animation-delay: .28s; }
    .hero__demo { animation-delay: .16s; }
    @keyframes lineUp { from { transform: translateY(105%); } to { transform: none; } }
    @keyframes fadeUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

    /* Die Vorfuehrung im Kopfbereich tritt zurueck, waehrend der Hero
       hinauslaeuft. Zwei Bewegungen an einem Element: die erste beim Laden
       an der Uhr, die zweite am Scrollen. Die zweite steht hinten und
       gewinnt deshalb, sobald ihr Bereich beginnt. */
    .hero__demo {
      animation: fadeUp .8s var(--ease) both, demoOut linear both;
      animation-delay: .16s, 0s;
      animation-timeline: auto, --hero;
      animation-range: normal, exit 18% exit 88%;
    }
    @keyframes demoOut {
      from { opacity: 1; transform: none; }
      to   { opacity: .34; transform: translateY(-6%) scale(.94); }
    }

    /* Der Strich vor der kleinen Zeile zieht sich, wenn der Abschnitt kommt */
    .eyebrow::before {
      animation: strichAuf linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 28%;
    }
    @keyframes strichAuf { from { transform: scaleX(0); } to { transform: scaleX(1); } }

    /* Zoom: das Fenster faehrt vom Ausschnitt auf volle Breite auf.
       Der Sinn ist nicht die Bewegung, sondern was am Ende dasteht:
       eine ganze Arbeitsansicht, die man danach anfassen kann. */
    .zoom {
      height: 280vh;
      padding-block: 0;
      view-timeline-name: --zoom;
    }
    .zoom__stage {
      position: sticky; top: 0;
      height: 100dvh;
      align-content: center;
      padding-top: var(--nav-h);
    }
    .zoom__frame {
      animation: frameIn linear both;
      animation-timeline: --zoom;
      animation-range: contain 0% contain 62%;
      transform-origin: center;
      will-change: transform;
    }
    @keyframes frameIn {
      from { transform: scale(.3); }
      to   { transform: scale(1); }
    }
    /* Die Zeile liegt ueber der Buehne, damit sie keinen Platz belegt.
       Sonst haengt das Fenster am Ende zu tief im Bild. */
    .zoom__head {
      position: absolute;
      top: 15%; left: var(--gutter); right: var(--gutter);
      margin-inline: auto;
      animation: headOut linear both;
      animation-timeline: --zoom;
      animation-range: contain 10% contain 40%;
    }
    @keyframes headOut {
      from { opacity: 1; transform: none; }
      to   { opacity: 0; transform: translateY(-24px); }
    }

    /* Kapitelanfang: die obere Kante laeuft von rund auf scharf.
       Bewusst nur border-radius. Ein transform oder clip-path auf diesem
       Block wuerde den sticky-Sektionen darin den Bezug nehmen. */
    .chapter {
      animation: chapterIn linear both;
      animation-timeline: view(block);
      animation-range: entry 0% entry 90%;
    }
    @keyframes chapterIn {
      from { border-radius: 44px 44px 0 0; }
      to   { border-radius: 0; }
    }

    /* Leistungen: die Spalten kommen versetzt herein. Mehr braucht der
       Abschnitt nicht, er soll auf einen Blick lesbar sein. */
    .services__grid { view-timeline-name: --svc; }
    .services__grid .card {
      animation: cardIn linear both;
      animation-timeline: --svc;
      animation-range-start: entry calc(30% + var(--n) * 6%);
      animation-range-end:   entry calc(72% + var(--n) * 6%);
    }
    @keyframes cardIn {
      from { opacity: 0; transform: translateY(22px); }
      to   { opacity: 1; transform: none; }
    }

    /* Ablauf: die Linie zeichnet sich mit, sie zeigt an, wie weit man ist */
    .flow__list { view-timeline-name: --flow; }
    .flow__list::after {
      animation: draw linear both;
      animation-timeline: --flow;
      animation-range: entry 60% exit 40%;
    }
    @keyframes draw { from { transform: scaleY(0); } to { transform: scaleY(1); } }

    /* Arbeiten: leichte Tiefe, damit das Raster nicht flach klebt.
       Dazu wandert der Bildausschnitt im Rahmen mit — ueber object-position,
       nicht ueber transform. Der Rahmen bleibt so genau da, wo er steht,
       und nur das Bild darin bewegt sich.
       Die Farbe kommt zurueck, wenn das Bild in der Mitte steht. Auf dem
       Handy gibt es kein hover, dort waere es sonst dauerhaft grau. */
    .work__item img {
      animation: workPan linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
    @keyframes rise {
      from { transform: scale(1.06) translateY(2%); }
      to   { transform: scale(1) translateY(0); }
    }
    @keyframes workPan {
      from { object-position: 50% 36%; filter: grayscale(1) contrast(1.04); }
      45%  { filter: grayscale(0) contrast(1); }
      to   { object-position: 50% 64%; filter: grayscale(0) contrast(1); }
    }

    /* Das Fenster selbst setzt sich auf wie die Vorfuehrungen im Kapitel */
    .work__panel {
      animation: panelIn linear both;
      animation-timeline: view();
      animation-range: entry 4% cover 40%;
      transform-origin: center top;
    }
    /* Die Bildunterschrift kommt nach dem Bild, nicht mit ihm */
    .work__item figcaption {
      animation: cardIn linear both;
      animation-timeline: view();
      animation-range: entry 25% cover 46%;
    }

    /* Die beiden grossen Fenster im dunklen Kapitel setzen sich auf.
       Etwas mehr Weg als bei .reveal, weil sie das Schwerste auf der
       Seite sind und sonst einfach dastehen. */
    .split__demo .panel,
    .wws .panel {
      animation: panelIn linear both;
      animation-timeline: view();
      animation-range: entry 4% cover 42%;
      transform-origin: center top;
    }
    /* Ein Hauch Neigung. Sie endet bei null, sonst waeren die Knoepfe
       darin schief zu treffen. */
    @keyframes panelIn {
      from { opacity: 0; transform: perspective(1400px) translateY(42px) rotateX(5deg) scale(.962); }
      to   { opacity: 1; transform: perspective(1400px) translateY(0) rotateX(0deg) scale(1); }
    }

    /* Die Haken laufen die Liste hinunter */
    .ticks { view-timeline-name: --ticks; }
    .ticks li {
      animation: tickIn linear both;
      animation-timeline: --ticks;
      animation-range-start: entry calc(20% + var(--n) * 12%);
      animation-range-end:   entry calc(75% + var(--n) * 12%);
    }
    @keyframes tickIn {
      from { opacity: 0; transform: translateX(-14px); }
      to   { opacity: 1; transform: none; }
    }

    /* Ablauf: die Schritte erscheinen in der Reihenfolge, in der die Linie
       sie erreicht. Beide haengen an derselben Zeitachse, also laufen sie
       zusammen und nicht gegeneinander. */
    .flow__step {
      animation: cardIn linear both;
      animation-timeline: --flow;
      animation-range-start: entry calc(52% + var(--n) * 9%);
      animation-range-end:   entry calc(86% + var(--n) * 9%);
    }

    /* Zusagen und Pakete: dieselbe versetzte Bewegung wie bei den Leistungen,
       damit die Seite eine Handschrift behaelt statt drei. */
    .stance__items { view-timeline-name: --stance; }
    .stance__item {
      animation: cardIn linear both;
      animation-timeline: --stance;
      animation-range-start: entry calc(22% + var(--n) * 11%);
      animation-range-end:   entry calc(72% + var(--n) * 11%);
    }

    .plans__grid { view-timeline-name: --plans; }
    .plans__grid .plan {
      animation: cardIn linear both;
      animation-timeline: --plans;
      animation-range-start: entry calc(24% + var(--n) * 10%);
      animation-range-end:   entry calc(74% + var(--n) * 10%);
    }
    /* Der Preis ist die Zeile, auf die gesehen wird. Er kommt zuletzt. */
    .plan__price {
      animation: priceIn linear both;
      animation-timeline: --plans;
      animation-range-start: entry calc(40% + var(--n) * 10%);
      animation-range-end:   entry calc(88% + var(--n) * 10%);
    }
    @keyframes priceIn {
      from { opacity: 0; transform: translateY(14px); }
      to   { opacity: 1; transform: none; }
    }

    /* Anfrage: die Felder bauen sich von oben nach unten auf, der Knopf
       zuletzt. Angesprochen werden nur diese beiden — die Falle und das
       versteckte Feld sollen gar nicht erst mitspielen. */
    .form { view-timeline-name: --form; }
    .form .field,
    .form .btn {
      animation: cardIn linear both;
      animation-timeline: --form;
      animation-range-start: entry calc(14% + var(--n) * 8%);
      animation-range-end:   entry calc(60% + var(--n) * 8%);
    }

    /* Der Fuss ist das Letzte auf der Seite. Sein Bereich endet, sobald er
       ganz im Bild steht: darunter liegt nichts mehr, was noch scrollen
       koennte, und ein Bereich bis „cover" liefe nie zu Ende. */
    .foot__inner {
      animation: reveal linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 100%;
    }
  }
}

/* ---------- 5b Bewegung ohne scroll-driven animations -------- */
/* Firefox kennt view() und scroll() noch nicht durchgehend, und in
   manchen Fassungen sind sie ausgeschaltet. Dort blieb die Seite bisher
   stumm stehen: der Fortschrittsbalken unsichtbar, die Bilder grau, die
   Linie im Ablauf ungezeichnet, weil all das im CSS bei null anfaengt und
   nur eine Zeitachse es weiterbewegt.

   Deshalb dieselbe Bewegung ein zweites Mal, hier mit Uebergaengen statt
   Zeitachsen. Der Eintritt laeuft einmal ab, wenn das Element ins Bild
   kommt (main.js setzt .drin), und die drei fortlaufenden Bewegungen
   haengen an Zahlen, die main.js beim Scrollen setzt.

   Die Klasse .bewegt kommt nur vom Skript, und nur wenn @supports oben
   scheitert und der Besucher Bewegung nicht abgelehnt hat. Ohne Skript
   steht die Seite genau so da wie vorher: alles sichtbar, nichts
   versteckt. Ein Element, das niemand einblenden kann, darf hier nie
   unsichtbar anfangen. */

.bewegt { --fortschritt: 0; }

/* Lesefortschritt und Gewicht der Leiste */
.bewegt .progress { transform: scaleX(var(--fortschritt)); transform-origin: left; }
.bewegt.tief .nav { box-shadow: 0 10px 30px rgba(13, 13, 15, .07); }

@media (prefers-reduced-motion: no-preference) {

  /* Eintritt: dieselben Wege wie in den Keyframes oben. */
  .bewegt .reveal,
  .bewegt .rise,
  .bewegt .foot__inner,
  .bewegt .services__grid .card,
  .bewegt .flow__step,
  .bewegt .stance__item,
  .bewegt .plans__grid .plan,
  .bewegt .plan__price,
  .bewegt .work__panel,
  .bewegt .work__item figcaption,
  .bewegt .split__demo .panel,
  .bewegt .wws .panel,
  .bewegt .ticks li,
  .bewegt .form .field,
  .bewegt .form .btn {
    opacity: 0;
    transition: opacity .8s var(--ease), transform .8s var(--ease);
    transition-delay: calc(var(--n, 0) * 80ms);
    will-change: opacity, transform;
  }

  .bewegt .reveal, .bewegt .foot__inner { transform: translateY(26px); }
  .bewegt .rise { transform: translateY(38px) scale(.985); }
  .bewegt .services__grid .card,
  .bewegt .flow__step,
  .bewegt .stance__item,
  .bewegt .plans__grid .plan,
  .bewegt .work__item figcaption,
  .bewegt .form .field,
  .bewegt .form .btn { transform: translateY(22px); }
  .bewegt .plan__price { transform: translateY(14px); }
  .bewegt .ticks li { transform: translateX(-14px); }
  /* Die schweren Fenster kommen wie oben mit einem Hauch Neigung. */
  .bewegt .work__panel,
  .bewegt .split__demo .panel,
  .bewegt .wws .panel {
    transform: perspective(1400px) translateY(42px) rotateX(5deg) scale(.962);
    transform-origin: center top;
  }

  .bewegt .drin { opacity: 1; transform: none; will-change: auto; }
  /* Bei den Fenstern bleibt die Perspektive stehen, sonst springt die
     Kante am Ende der Bewegung. */
  .bewegt .work__panel.drin,
  .bewegt .split__demo .panel.drin,
  .bewegt .wws .panel.drin {
    transform: perspective(1400px) translateY(0) rotateX(0deg) scale(1);
  }

  /* Der Strich vor der kleinen Zeile */
  .bewegt .eyebrow::before {
    transform: scaleX(0);
    transition: transform .7s var(--ease);
  }
  .bewegt .eyebrow.drin::before { transform: scaleX(1); }

  /* Die Linie im Ablauf zeichnet sich, sobald die Liste im Bild steht.
     Sie haengt hier an der Uhr und nicht am Scrollen: der Sinn ist, dass
     sie ueberhaupt entsteht. */
  .bewegt .flow__list::after { transition: transform 1.6s var(--ease); }
  .bewegt .flow__list.drin::after { transform: scaleY(1); }

  /* Farbe zurueck ins Bild, wenn es im Bild steht. Ohne das bleibt das
     Raster auf dem Handy dauerhaft grau, weil es dort kein hover gibt. */
  .bewegt .work__item img.drin { filter: grayscale(0) contrast(1); }

  /* Die obere Kante des Kapitels laeuft von rund auf scharf */
  .bewegt .chapter { border-radius: 44px 44px 0 0; transition: border-radius 1s var(--ease); }
  .bewegt .chapter.drin { border-radius: 0; }

  /* Kopfbereich: Zeilen fahren beim Laden ein, wie oben */
  .bewegt .hero__title .line > span { animation: lineUp .95s var(--ease) both; }
  .bewegt .hero__title .line:nth-child(2) > span { animation-delay: .09s; }
  .bewegt .hero__sub, .bewegt .hero__actions, .bewegt .hero__demo {
    animation: fadeUp .8s var(--ease) both;
  }
  .bewegt .hero__sub { animation-delay: .2s; }
  .bewegt .hero__actions { animation-delay: .28s; }
  .bewegt .hero__demo { animation-delay: .16s; }

  /* Parallaxe im Kopfbereich. --herop laeuft von 0 bis 1, waehrend der
     Kopfbereich hinauslaeuft. */
  .bewegt .hero { --herop: 0; }
  .bewegt .hero__bg {
    transform: translate3d(0, calc(-2% + 11% * var(--herop)), 0) scale(1.06);
    will-change: transform;
  }
  .bewegt .hero__glow {
    opacity: calc(.62 - .44 * var(--herop));
    transform: translate3d(calc(-4% * var(--herop)), calc(8% * var(--herop)), 0)
               scale(calc(1 + .16 * var(--herop)));
  }
  /* Die Vorfuehrung tritt zurueck, waehrend der Kopfbereich hinauslaeuft.
     Das Einfahren beim Laden haengt an der Animation auf .hero__demo.
     Eine Animation mit „both" gewinnt gegen jede gewoehnliche Angabe,
     deshalb liegt das Zuruecktreten eine Ebene tiefer, auf den Kindern:
     sonst haelt fadeUp die Deckkraft fuer immer auf 1. */
  .bewegt .hero__demo > * {
    opacity: calc(1 - .66 * var(--demoaus, 0));
    transform: translateY(calc(-6% * var(--demoaus, 0))) scale(calc(1 - .06 * var(--demoaus, 0)));
    transform-origin: center top;
  }

  /* Der Zoom auf die Betreiberansicht. Ohne Zeitachse braucht der
     Abschnitt dieselbe Hoehe und dieselbe klebende Buehne wie oben,
     sonst gibt es keinen Weg, auf dem etwas ablaufen koennte. */
  .bewegt .zoom {
    height: 280vh;
    padding-block: 0;
    --zoomp: 1;
    --kopfaus: 0;
  }
  .bewegt .zoom__stage {
    position: sticky; top: 0;
    height: 100dvh;
    align-content: center;
    padding-top: var(--nav-h);
  }
  .bewegt .zoom__frame {
    transform: scale(calc(.3 + .7 * var(--zoomp)));
    transform-origin: center;
    will-change: transform;
  }
  .bewegt .zoom__head {
    position: absolute;
    top: 15%; left: var(--gutter); right: var(--gutter);
    margin-inline: auto;
    opacity: calc(1 - var(--kopfaus));
    transform: translateY(calc(-24px * var(--kopfaus)));
  }
}

/* ---------- 6 Schmale Fenster ------------------------------- */

@media (max-width: 1180px) {
  .services__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 1000px) {
  .hero__grid { grid-template-columns: 1fr; }
  .hero { min-height: 0; padding-top: 2rem; }

  /* Einspaltig darf die Ueberschrift umbrechen. Eine Maske wuerde die
     zweite Zeile abschneiden, also faehrt der Text hier nur ein. */
  .hero__title .line { overflow: visible; }
  .hero__title .line > span { animation-name: fadeUp; }
  .split__grid,
  .contact__grid,
  .stance__grid { grid-template-columns: 1fr; }
  .stance__h { position: static; }
  .work__grid { grid-template-columns: 1fr; }
  .plans__grid { grid-template-columns: 1fr; }
  .plan--lead { grid-row: auto; }
}

@media (max-width: 760px) {
  :root { --nav-h: 60px; }

  .nav__links, .nav__cta { display: none; }
  .nav__burger { display: grid; }
  .nav__mobile {
    display: grid;
    padding: .5rem var(--gutter) 1.25rem;
    border-top: 1px solid var(--rule);
    background: var(--bg);
  }
  .nav__mobile[hidden] { display: none; }
  .nav__mobile a {
    padding: .85rem 0;
    text-decoration: none;
    border-bottom: 1px solid var(--rule);
    font-size: 1.0625rem;
  }
  .nav__mobile a:last-child { border-bottom: 0; color: var(--accent); }

  .hero__actions .btn { flex: 1 1 auto; }
  /* Schmal ist fuer eine echte Mitte kein Platz: der Titel stellt sich
     neben die Knoepfe, sonst laeuft er unter die Kennzeichnung. */
  .panel__title {
    position: static; transform: none;
    overflow: hidden; text-overflow: ellipsis;
  }
  .booking__slots { grid-template-columns: repeat(2, 1fr); }
  .services__grid { grid-template-columns: 1fr; }
  .week__detail { flex-direction: column; align-items: stretch; }
  .week__acts .btn { flex: 1; }
  .invoice__row { grid-template-columns: 1fr auto; row-gap: .5rem; }
  .invoice__line { grid-column: 2; }
  .invoice__del { grid-column: 2; justify-self: end; }
  .stock__table th:nth-child(3), .stock__table td:nth-child(3) { display: none; }
  .stock__table th, .stock__table td { padding: .7rem .6rem; }
  .stock__act .btn { padding-inline: .7rem; font-size: .8125rem; }
  .foot__inner { flex-direction: column; align-items: start; }
  .foot__brand { margin-right: 0; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition-duration: .01ms !important; }
}

@media (prefers-reduced-transparency: reduce) {
  .nav { background: var(--bg); backdrop-filter: none; -webkit-backdrop-filter: none; }
}
