/* ═══════════════════════════════════════════════════════════════════
   Startvorlage für statische Kundenseiten · AI Media Halle
   Aufbau abgetragen von einer früheren Kundenseite, aber auf
   CSS 2026 umgestellt: Kaskadenschichten, ein Farb-Token, native
   Einblendungen, native Feldgrößen.

   Stand 29.08.2026 · Linie Tempo (kein Video, kein WebGL, kein GSAP)
   Reihenfolge in dieser Datei:
     0. Schriftschnitte (@font-face — steht bewusst VOR den Schichten)
     1. @layer grundlage  — Reset, Token, Grundtypografie
     2. @layer bausteine  — Kopf, Bühne, Karten, Schaltflächen, Formular
     3. @layer ausnahmen  — Hilfsklassen, Weichen, Bewegungsabschaltung
   ═══════════════════════════════════════════════════════════════════ */

/* ── Kaskadenordnung: EINMAL hier, ganz oben, vor allem anderen ──────
   Wer später schreibt, gewinnt nicht mehr automatisch — es gewinnt die
   spätere SCHICHT. Damit kann eine Ausnahme mit einer einzigen Klasse
   einen Baustein überstimmen, ohne !important und ohne Spezifitätsspiel.
   (Haus-Regel „Komponentenklasse schlägt Utility": mit @layer ist die
   Reihenfolge explizit statt zufällig.)
   ACHTUNG: ungeschichtetes CSS schlägt JEDE Schicht. Alles, was in
   diesem Projekt dazukommt, gehört deshalb in eine der drei Schichten. */
@layer grundlage, bausteine, ausnahmen;

/* ── 0. Schriften ────────────────────────────────────────────────────
   Beide Dateien liegen lokal unter assets/fonts/ (Haus-Regel: keine
   Google-Fonts-Verbindung). Zwei variable Schnitte statt sechs statischer
   Dateien: 51 kB für den gesamten Gewichtsbereich 200–800.
   Vorgeladen werden sie in der index.html per rel="preload" … crossorigin —
   ohne crossorigin lädt der Browser sie ein zweites Mal.
   `size-adjust`/`ascent-override` nur setzen, wenn ein Ersatzschnitt
   nachgemessen wurde; sonst weglassen statt raten. */
@font-face {
  font-family: "Manrope";
  src: url("../fonts/Manrope-variabel-latin.woff2") format("woff2");
  font-weight: 200 800;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Jost";
  src: url("../fonts/Jost-variabel-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ═══════════════════════════════════════════════════════════════════
   1. @layer grundlage
   ═══════════════════════════════════════════════════════════════════ */
@layer grundlage {

  /* ── Farbsystem: EIN Marken-Token, alles andere abgeleitet ─────────
     Beim neuen Kunden wird genau --marke ausgetauscht (Wert vom
     Ladenschild / Logo abtragen, danach am Schirm gegenprüfen —
     OKLCH-Zahlen sind ein Bezugssystem, der Monitor ein anderes).
     Der Rest der Palette rechnet sich mit relativen Farben mit:
       oklch(from <quelle> L C H)  —  L/C/H sind die Kanäle der Quelle,
       mit calc() verschiebbar. L 0…1, C 0…~0.37, H in Grad.
     Warum das hier trägt: keine handgepflegte Palette, die beim
     Farbwechsel auseinanderfällt, und Hover-Töne, die IMMER zum
     Grundton passen — auch bei einem knalligen Kundenrot. */
  :root {
    --marke: oklch(0.549 0.19 31);          /* ← der einzige Handgriff · A0 Printlab: Rot #c8321e aus der Preisliste (noch kein Logo) */

    /* Tonleiter aus dem Marken-Token — heller nach oben, tiefer nach unten.
       Sättigung wird zu den hellen Stufen zurückgenommen, sonst kippen
       große Flächen ins Grelle. */
    --marke-hauch:   oklch(from var(--marke) 0.975 calc(c * 0.16) h);
    --marke-schleie: oklch(from var(--marke) 0.93  calc(c * 0.30) h);
    --marke-hell:    oklch(from var(--marke) calc(l + 0.14) calc(c * 0.88) h);
    --marke-tief:    oklch(from var(--marke) calc(l - 0.16) calc(c * 0.96) h);
    --marke-nacht:   oklch(from var(--marke) 0.24 calc(c * 0.70) h);

    /* Der Kontrast-Deckel — der Grund, warum dieses System auch mit einem
       hellen Kundenton hält.
       Ein einzelnes Marken-Token kann beliebig hell sein (Ocker, Gelb,
       Hellgrün). Als Textfarbe oder als Knopffläche mit hellem Text fällt
       es dann durch. Gemessen über 12 Farbwinkel bei C 0.16:
         L 0.50 → schlechtester Winkel 4,88:1   (trägt Text)
         L 0.55 → schlechtester Winkel 4,00:1   (fällt durch)
       Deshalb: alles, was Text SEIN oder Text TRAGEN muss, läuft über
       --marke-text. min() kappt nur nach oben — ein dunkler Kundenton
       bleibt unverändert er selbst. */
    --marke-text:   oklch(from var(--marke) min(l, 0.50) c h);

    /* Zustände: aus demselben Token, nicht aus einem zweiten Hex-Wert.
       Hover wird eine Spur dunkler UND satter — das liest sich als
       „gedrückt kommt noch", nicht als andere Farbe.
       Basis ist --marke-text, damit der Deckel mitwandert. */
    --marke-hover:  oklch(from var(--marke-text) calc(l - 0.06) calc(c * 1.08) h);
    --marke-aktiv:  oklch(from var(--marke-text) calc(l - 0.12) calc(c * 1.12) h);
    --marke-ruhig:  oklch(from var(--marke-text) l calc(c * 0.45) h);  /* deaktiviert */

    /* Neutrale mit einem Hauch Markenton — dadurch wirkt die Seite aus
       einem Guss statt „farbige Knöpfe auf grauem Papier". */
    --papier:    oklch(from var(--marke) 0.99  calc(c * 0.05) h);
    --flaeche:   oklch(from var(--marke) 0.965 calc(c * 0.09) h);
    --linie:     oklch(from var(--marke) 0.90  calc(c * 0.10) h);  /* NUR Deko */
    --gedaempft: oklch(from var(--marke) 0.52  calc(c * 0.12) h);
    --tinte:     oklch(from var(--marke) 0.24  calc(c * 0.18) h);

    /* --linie (1,31:1) ist eine Zierlinie und darf NIE der Rand eines
       Bedienelements sein: Eingabefelder und Knöpfe brauchen 3:1 gegen
       ihre Umgebung (WCAG 1.4.11). Dafür --rand — bei L 0.62 gemessen
       3,25:1 im schlechtesten der 12 geprüften Farbwinkel. */
    --rand:      oklch(from var(--marke) 0.62  calc(c * 0.20) h);

    /* Akzent: Gegenton, ebenfalls abgeleitet (Winkel gedreht).
       Sparsam einsetzen — Preis, Öffnungszeit, ein Fehlerhinweis.
       L 0.52 statt 0.62: als Hinweistext braucht der Akzent 4,5:1, und
       bei 0.62 lag er außerdem außerhalb des sRGB-Raums (der Browser
       hätte ihn beim Anzeigen verbogen). */
    --akzent:    oklch(from var(--marke) 0.52 calc(c * 0.95) calc(h + 155));

    /* Fokusring: muss auf hellem UND dunklem Grund sichtbar bleiben.
       Gemessen 4,24:1 auf --papier und 3,80:1 auf --marke-nacht. */
    --fokus:     oklch(from var(--marke) 0.58 calc(c * 1.35) h);

    /* ── Typografie ── */
    --schrift-display: "Jost", "Futura", "Century Gothic", system-ui, sans-serif;
    --schrift-text: "Manrope", "Segoe UI", system-ui, sans-serif;

    /* Stufen mit clamp: kein Media-Query nötig, kein Sprung dazwischen.
       --t-xxl ist bewusst bei 4rem gedeckelt und nicht bei 5rem: gemessen
       am 29.08.2026 bei 1536×864 (125 % Windows-Skalierung auf 1080p, der
       Normalfall) schob eine 80-px-Überschrift den Terminknopf auf y=1159
       — 295 px unter den Falz. Eine Startseite, deren Hauptknopf beim Laden
       nicht zu sehen ist, verfehlt ihren Zweck. */
    --t-xxl: clamp(2.4rem, 1.5rem + 3.4vw, 4rem);
    --t-xl:  clamp(2rem,   1.4rem + 2.6vw, 3.25rem);
    --t-l:   clamp(1.45rem, 1.2rem + 1.1vw, 2rem);
    --t-m:   clamp(1.1rem, 1.03rem + 0.32vw, 1.28rem);
    --t-s:   0.9rem;
    --t-xs:  0.76rem;

    /* ── Maße ── */
    --breite: 72rem;          /* Inhaltsbreite */
    --luft: clamp(1.25rem, 4vw, 3rem);   /* Seitenrand */
    --abstand: clamp(3.5rem, 8vw, 7rem); /* Abschnittsabstand */
    --radius: 0.75rem;
    --kopf-hoehe: 4.25rem;

    /* ── Takt ── */
    --weich-raus: cubic-bezier(0.23, 1, 0.32, 1);
    --weich-beide: cubic-bezier(0.65, 0, 0.35, 1);
    --takt-ui: 180ms;
    --takt-auftritt: 620ms;

    color-scheme: light;
    accent-color: var(--marke-text);
    interpolate-size: allow-keywords;  /* height: auto wird animierbar (aus einem Kundenprojekt) */
  }

  /* ── Gemessene Kontraste beim Standard-Token oklch(0.52 0.13 258) ──
     Nachgerechnet am 29.08.2026, nicht geschätzt:
       Fließtext   --tinte     auf --papier        15,97:1   AAA
       Nebentext   --gedaempft auf --papier         5,35:1   AA
       Augenmaß    --marke-text auf --papier        5,40:1   AA
       Knopftext   --papier    auf --marke-text     5,40:1   AA
       Knopf hover --papier    auf --marke-hover    7,03:1   AAA
       Fuß         --papier    auf --marke-nacht   16,11:1   AAA
       Hinweis     --akzent    auf --papier         5,59:1   AA
       Feldrand    --rand      auf --papier         3,53:1   AA (1.4.11)
       Fokusring   --fokus     auf --papier         4,24:1   AA (2.4.11)
     Nach dem Tausch von --marke bleiben diese Werte nicht automatisch
     gleich — die Formeln halten sie in der Nähe, aber die Prüfung gehört
     wiederholt (Haus-Regel: übernommener Messwert trägt sein Bezugssystem). */

  /* ── Reset (knapp gehalten, keine Fremdbibliothek) ── */
  *, *::before, *::after { box-sizing: border-box; }
  * { margin: 0; padding: 0; }

  html {
    scrollbar-gutter: stable;        /* kein Springen, wenn ein Dialog aufgeht */
    scroll-behavior: smooth;
    scroll-padding-top: calc(var(--kopf-hoehe) + 1rem);  /* Ankerziel nicht unter den Kopf */
    -webkit-text-size-adjust: 100%;
  }

  body {
    font-family: var(--schrift-text);
    font-size: 1.0625rem;
    font-weight: 400;
    line-height: 1.65;
    color: var(--tinte);
    background: var(--papier);
    -webkit-font-smoothing: antialiased;
    overflow-x: clip;
    min-height: 100svh;
  }

  img, video, canvas, svg { display: block; max-width: 100%; }
  img { height: auto; }
  a { color: inherit; }
  ul, ol { list-style: none; }
  button, input, select, textarea { font: inherit; color: inherit; }

  /* ── Umbruch: der eigentliche Gewinn dieser Datei ohne eine Zeile JS ──
     balance  → verteilt eine Überschrift gleichmäßig auf ihre Zeilen,
                statt eine Schlusszeile mit einem Wort stehen zu lassen.
                Der Browser rechnet das nur bis ~6 Zeilen; für Überschriften
                genau richtig, für Fließtext zu teuer.
     pretty   → verhindert Schusterjungen am Absatzende und (in aktuellen
                Browsern) schlechte Trennungen; für lange Texte gebaut. */
  h1, h2, h3 {
    font-family: var(--schrift-display);
    font-weight: 560;
    line-height: 1.08;
    letter-spacing: -0.015em;
    text-wrap: balance;
  }
  h4, h5, h6, blockquote, figcaption, .balance {
    text-wrap: balance;
  }
  h1 { font-size: var(--t-xxl); }
  h2 { font-size: var(--t-xl); }
  h3 { font-size: var(--t-l); }

  p, li, dd, .fliess, .fliess * {
    text-wrap: pretty;
  }
  p { max-width: 62ch; }   /* Lesebreite; im Baustein bei Bedarf aufheben */

  /* ── Fokus: sichtbar, aber nicht laut. Nie entfernen. ── */
  :focus-visible {
    outline: 2px solid var(--fokus);
    outline-offset: 3px;
    border-radius: 4px;
  }
  :focus:not(:focus-visible) { outline: none; }

  /* ── Nur für Screenreader ──
     clip-path statt clip; NICHT display:none — das nähme den Text auch
     dem Screenreader. Haus-Regel „unsichtbare Texte übersetzen": diese
     Texte gehören mit ins Korrektorat. */
  .sr-nur {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  ::selection { background: var(--marke-schleie); color: var(--tinte); }
}

/* ═══════════════════════════════════════════════════════════════════
   2. @layer bausteine
   ═══════════════════════════════════════════════════════════════════ */
@layer bausteine {

  /* ── Raster ── */
  .huelle {
    width: min(100% - 2 * var(--luft), var(--breite));
    margin-inline: auto;
  }
  .abschnitt { padding-block: var(--abstand); }
  .abschnitt--flaeche { background: var(--flaeche); }
  .abschnitt__kopf { margin-bottom: clamp(2rem, 4vw, 3.25rem); }
  .abschnitt__kopf p { color: var(--gedaempft); margin-top: 0.85rem; }

  .augenmass {
    font-family: var(--schrift-display);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--marke-text);
    display: block;
    margin-bottom: 0.9rem;
  }

  /* ── Kopf ──
     Der Schatten kommt erst, wenn der Kopf wirklich klebt — Scroll-State-
     Query statt JS-Sentinel. Ohne Unterstützung bleibt der Kopf schlicht
     schattenlos; das ist ein zulässiger Zustand, kein Ausfall.
     NACHGEMESSEN am 29.08.2026, Chromium 151: die Abfrage löst dort NIE
     aus, obwohl CSS.supports() sie erkennt und der Kopf nachweislich
     klebt. Der Block bleibt trotzdem stehen — er kostet nichts und greift
     von allein, sobald die Browser nachziehen. Wer den Schatten heute
     wirklich braucht, zahlt dafür einen IntersectionObserver-Sentinel. */
  .kopf {
    position: sticky;
    top: 0;
    z-index: 20;
    height: var(--kopf-hoehe);
    display: flex;
    align-items: center;
    background: color-mix(in oklab, var(--papier) 86%, transparent);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid transparent;
    transition: border-color var(--takt-ui), box-shadow var(--takt-ui);
    container-type: scroll-state;
  }
  @container scroll-state((stuck: top)) {
    .kopf {
      border-bottom-color: var(--linie);
      box-shadow: 0 8px 28px -22px var(--marke-nacht);
    }
  }
  /* KEIN width: 100% hier. `.kopf__innen` trägt zugleich `.huelle`, und
     beide liegen in derselben Schicht — die spätere Regel gewann und zog
     die Kopfzeile auf die volle Fensterbreite, während der Inhalt darunter
     bei x=185 begann. Der Versatz war nur auf dem Schirm zu sehen, keine
     der Messungen schlug an (29.08.2026). */
  .kopf__innen {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
  }
  .kopf__marke {
    font-family: var(--schrift-display);
    font-size: 1.2rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-decoration: none;
  }
  .kopf__nav ul { display: flex; gap: clamp(1rem, 2.5vw, 2rem); align-items: center; }
  .kopf__nav a {
    text-decoration: none;
    font-size: var(--t-s);
    color: var(--gedaempft);
    transition: color var(--takt-ui);
  }
  .kopf__nav a:hover { color: var(--marke-hover); }
  @media (max-width: 44rem) {
    .kopf__nav ul li:not(:last-child) { display: none; }
  }

  /* ── Bühne ── */
  .buehne {
    padding-block: clamp(4rem, 12vh, 8rem) var(--abstand);
    background:
      radial-gradient(120% 90% at 15% -10%, var(--marke-schleie), transparent 62%),
      var(--papier);
  }
  /* Überschrift und Absatz brauchen VERSCHIEDENE Maße.
     Eine gemeinsame Spalte von 44ch ist für den Fließtext richtig und für
     eine 64-px-Überschrift viel zu schmal: sie zerfiel dort in sieben
     Zeilen (gemessen 691 px hoch) und drückte den Terminknopf unter den
     Falz. 44ch bemisst sich an der Schriftgröße des Elements — bei der
     Überschrift ist ein „ch" fast doppelt so breit wie im Fließtext. */
  .buehne__text > * { max-width: 46ch; }
  .buehne h1 { max-width: 22ch; }
  .buehne h1 + p {
    font-size: var(--t-m);
    color: var(--gedaempft);
    margin-top: 1.4rem;
  }
  .buehne__knoepfe { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 2.2rem; }

  /* ── Schaltflächen ──
     Alle Zustände kommen aus --marke. Ein Kundenwechsel braucht hier
     keine einzige Änderung. */
  .knopf {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.8rem 1.5rem;
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: var(--t-s);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    background: var(--marke-text);   /* gedeckelt: trägt hellen Text bei jedem Kundenton */
    color: var(--papier);
    transition:
      background-color var(--takt-ui) var(--weich-raus),
      translate var(--takt-ui) var(--weich-raus),
      box-shadow var(--takt-ui) var(--weich-raus);
  }
  .knopf:hover { background: var(--marke-hover); translate: 0 -2px; box-shadow: 0 10px 24px -14px var(--marke-nacht); }
  .knopf:active { background: var(--marke-aktiv); translate: 0; box-shadow: none; }
  .knopf[disabled], .knopf[aria-disabled="true"] {
    background: var(--marke-ruhig);
    cursor: not-allowed;
    translate: 0;
    box-shadow: none;
  }
  .knopf--leise {
    background: transparent;
    color: var(--marke-text);
    border-color: var(--rand);   /* Bedienelement, nicht Zierlinie: 3:1 */
  }
  .knopf--leise:hover {
    background: var(--marke-hauch);
    border-color: var(--marke-hell);
    color: var(--marke-hover);
  }

  /* ── Karten ── */
  .karten {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
    gap: clamp(1rem, 2.5vw, 1.75rem);
  }
  .karte {
    padding: clamp(1.5rem, 3vw, 2.1rem);
    background: var(--papier);
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    transition: border-color var(--takt-ui), translate var(--takt-ui) var(--weich-raus);
  }
  .karte:hover { border-color: var(--marke-hell); translate: 0 -3px; }
  .karte h3 { font-size: var(--t-l); margin-bottom: 0.7rem; }
  .karte p { color: var(--gedaempft); font-size: var(--t-s); max-width: none; }
  .karte__ziffer {
    font-family: var(--schrift-display);
    font-size: var(--t-l);
    color: var(--marke-text);   /* --marke-hell ist Flächen- und Randton, nie Text */
    display: block;
    margin-bottom: 0.9rem;
  }

  /* ── Einblenden: @starting-style statt Keyframes und IntersectionObserver ──
     @starting-style beschreibt den Zustand, aus dem heraus ein Element
     das ERSTE Mal gerendert wird. Der Browser fährt von dort in den
     normalen Zustand — mit einem gewöhnlichen transition, ohne Klasse,
     ohne Skript, ohne Layout-Sprung.
     Wichtig und bewusst so gebaut: der Ziel-Zustand ist der SICHTBARE.
     Ein Browser ohne @starting-style zeigt das Element einfach sofort —
     nie eine leere Seite (Haus-Regel „ohne Rückfallweg bleiben Abschnitte
     unsichtbar"). Deshalb ist hier auch kein @supports nötig. */
  .auftritt {
    opacity: 1;
    translate: 0 0;
    transition:
      opacity var(--takt-auftritt) var(--weich-raus),
      translate var(--takt-auftritt) var(--weich-raus);

    @starting-style {
      opacity: 0;
      translate: 0 1.4rem;
    }
  }
  /* Staffelung ohne nth-child-Kaskade: der Geschwister-Index rechnet mit.
     Wo sibling-index() fehlt, starten alle gleichzeitig — auch das ist
     ein zulässiger Zustand. */
  .auftritt--reihe > * {
    opacity: 1;
    translate: 0 0;
    transition:
      opacity var(--takt-auftritt) var(--weich-raus),
      translate var(--takt-auftritt) var(--weich-raus);
    transition-delay: calc(sibling-index() * 70ms);

    @starting-style {
      opacity: 0;
      translate: 0 1.4rem;
    }
  }

  /* Dialog und Popover: hier ist @starting-style der eigentliche Zweck —
     das Element existiert vorher gar nicht im Rendering. */
  dialog {
    margin: auto;
    max-width: min(34rem, calc(100% - 2rem));
    padding: clamp(1.5rem, 4vw, 2.25rem);
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--papier);
    color: var(--tinte);
    opacity: 1;
    scale: 1;
    transition:
      opacity 240ms var(--weich-raus),
      scale 240ms var(--weich-raus),
      overlay 240ms allow-discrete,
      display 240ms allow-discrete;

    @starting-style {
      opacity: 0;
      scale: 0.96;
    }
  }
  dialog:not([open]) { opacity: 0; scale: 0.96; }
  dialog::backdrop {
    background: color-mix(in oklab, var(--marke-nacht) 55%, transparent);
    backdrop-filter: blur(2px);
    opacity: 1;
    transition:
      opacity 240ms var(--weich-raus),
      overlay 240ms allow-discrete,
      display 240ms allow-discrete;

    @starting-style { opacity: 0; }
  }
  dialog:not([open])::backdrop { opacity: 0; }

  /* ── Formular ──
     field-sizing: content lässt das Feld mit dem Inhalt wachsen — kein
     Auto-Resize-Skript, kein Scrollbalken im Textfeld, kein abgeschnittener
     Satz beim Vorlesen. Die Grenzen stehen in lh (Zeilenhöhen), nicht in
     Pixeln: so bleibt das Feld bei jeder Schriftgröße und in jeder
     Zoomstufe genau vier bis zwanzig Zeilen groß.
     ABWEICHUNG vom Auftrag, bewusst: 4lh Mindesthöhe gilt NUR für
     <textarea>. Ein einzeiliges <input> vier Zeilen hoch zu machen wäre
     ein Gestaltungsfehler — Einzeiler bekommen 1lh und wachsen in der
     Breite. Ohne field-sizing greifen rows/size wie bisher. */
  .formular {
    display: grid;
    gap: 1.15rem;
    max-width: 34rem;
  }
  .feld { display: grid; gap: 0.4rem; }
  .feld > label {
    font-size: var(--t-s);
    font-weight: 600;
  }
  .feld > .hinweis {
    font-size: var(--t-xs);
    color: var(--gedaempft);
  }

  .formular :is(input, select, textarea) {
    field-sizing: content;
    padding: 0.7rem 0.9rem;
    background: var(--papier);
    border: 1px solid var(--rand);   /* NICHT --linie: Feldrand muss 3:1 tragen */
    border-radius: 0.5rem;
    transition: border-color var(--takt-ui), background-color var(--takt-ui);
  }
  /* Einzeiler: eine Zeile hoch, wachsen seitlich — mit Deckel, damit ein
     langer Wert das Raster nicht aufreißt. */
  .formular :is(input, select) {
    min-height: 1lh;
    min-width: 12rem;
    max-width: 100%;
  }
  /* Mehrzeiler: die vier bis zwanzig Zeilen aus dem Auftrag. */
  .formular textarea {
    min-height: 4lh;
    max-height: 20lh;
    resize: vertical;
    line-height: 1.55;
  }
  .formular :is(input, select, textarea):hover { border-color: var(--marke-hell); }
  .formular :is(input, select, textarea):focus-visible {
    border-color: var(--marke-text);
    background: var(--marke-hauch);
  }
  .formular :is(input, textarea):user-invalid {
    border-color: var(--akzent);
  }
  .formular :is(input, textarea):user-invalid + .hinweis { color: var(--akzent); }

  /* ── Fuß ── */
  .fuss {
    padding-block: clamp(2.5rem, 5vw, 4rem);
    background: var(--marke-nacht);
    color: color-mix(in oklab, var(--papier) 82%, transparent);
    font-size: var(--t-s);
  }
  .fuss a { color: var(--papier); text-decoration-color: color-mix(in oklab, var(--papier) 40%, transparent); }
  .fuss a:hover { text-decoration-color: currentColor; }
  .fuss__reihen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
    gap: 2rem;
  }
  .fuss h2, .fuss h3 { color: var(--papier); font-size: var(--t-s); letter-spacing: 0.14em; text-transform: uppercase; margin-bottom: 0.8rem; }
  .fuss__zeile {
    margin-top: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid color-mix(in oklab, var(--papier) 18%, transparent);
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    justify-content: space-between;
    font-size: var(--t-xs);
  }
}

/* ═══════════════════════════════════════════════════════════════════
   3. @layer ausnahmen
   Alles, was einen Baustein überstimmen darf. Weil diese Schicht zuletzt
   deklariert ist, reicht dafür eine einzelne Klasse — kein !important.
   ═══════════════════════════════════════════════════════════════════ */
@layer ausnahmen {

  .eng   { max-width: 46rem; }
  .weit  { max-width: none; }
  .mitte { margin-inline: auto; text-align: center; }
  .mitte p { margin-inline: auto; }
  .leise { color: var(--gedaempft); }
  .laut  { color: var(--marke-text); }   /* nie var(--marke): das ist die ungedeckelte Fassung */
  .kein-abstand-oben   { padding-block-start: 0; }
  .kein-abstand-unten  { padding-block-end: 0; }

  /* ── Bewegungsabschaltung ──
     Ein einziger Block, ganz am Ende der letzten Schicht: er überstimmt
     jede Regel dieser Datei. Nicht auf 0 gesetzt, sondern auf 0,01 ms —
     so laufen transitionend/animationend weiter und Skripte, die darauf
     warten, bleiben nicht hängen.
     Pflicht im Haus (und im Vertrieb ein Argument): wer Bewegung nicht
     verträgt, bekommt dieselbe Seite ohne Bewegung, nicht eine kaputte. */
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      transition-delay: 0ms !important;
      scroll-behavior: auto !important;
    }
    /* Die Einblendungen dürfen nicht nur „schnell" sein, sondern gar
       nicht erst aus dem Versatz starten. */
    .auftritt, .auftritt--reihe > * {
      @starting-style {
        opacity: 1;
        translate: 0 0;
      }
    }
    .knopf:hover, .karte:hover { translate: 0; }
    html { scroll-behavior: auto; }
  }

  /* ── Sparsamer Datentarif: Verläufe und Weichzeichner kosten Rechenzeit ── */
  @media (prefers-reduced-transparency: reduce) {
    .kopf { backdrop-filter: none; background: var(--papier); }
    dialog::backdrop { backdrop-filter: none; }
  }

  /* ── Druck ── */
  @media print {
    .kopf, .buehne__knoepfe, .formular { display: none; }
    body { background: #fff; color: #000; }
    .abschnitt { padding-block: 1rem; }
  }
}
