/* ============================================================================
   VR Digital Portal — Oberfläche

   Ein Arbeitswerkzeug, keine Werbeseite. Zielgruppe sind Gastronomen und
   Handwerker, die am Handy zwischen zwei Terminen die Tageskarte ändern —
   nicht Gestalter am 27-Zoll-Bildschirm.

   ---------------------------------------------------------------------------
   GESTALTUNG: DIESELBE SPRACHE WIE vrdigital-studio.de

   Die Studio-Webseite steht auf der Idee „Debossed Paper": Die Fläche IST ein
   Bogen Papier. Inhalte sind entweder auf das Papier gedruckt oder in es
   hineingeprägt — Prägung heißt: keine Farbe, nur zwei gegenläufige Schatten
   entlang einer Lichtrichtung.

   Das Portal übernimmt Farben, Schriften und diese Prägung. Ein Kunde, der von
   der Webseite kommt, soll nicht das Gefühl haben, bei einem anderen Anbieter
   gelandet zu sein.

   WAS ES NICHT ÜBERNIMMT: das Licht, das dem Mauszeiger folgt. Auf der
   Webseite ist das die Signatur; hier wäre es ein Skript, das bei jeder
   Mausbewegung rechnet — für eine Oberfläche, die überwiegend am Handy bedient
   wird (kein Zeiger) und in der man arbeitet statt staunt. Die Lichtrichtung
   steht deshalb fest.

   Farben, Schriften und Grundsätze stammen aus dem Vault:
   `Wissen/Webseite-Technik-und-Design.md`.

   ---------------------------------------------------------------------------
   REGELN, DIE NICHT VERHANDELBAR SIND

   · Keine fremde Quelle. Die CSP führt `default-src 'self'` — Schriften liegen
     unter assets/fonts/, Muster sind data:-URIs.
   · Klickflächen mindestens 44 px. Kleiner trifft niemand am Handy zuverlässig.
   · Eingabefelder mindestens 16 px Schriftgröße, sonst zoomt iOS beim Antippen.
   · Tastaturfokus immer sichtbar.
   · Dunkelmodus bleibt. Die Webseite ist bewusst hell, aber wer abends in der
     Küche am Handy die Karte ändert, bekommt sonst eine Leuchtfläche ins
     Gesicht. Hier ist es dunkel getöntes Papier, kein neutrales Grau.
   ========================================================================== */

/* `schriften.css` wird im Rahmen davor eingebunden, nicht per @import: Ein
   @import wird erst entdeckt, wenn diese Datei bereits geladen ist, und hängt
   damit einen zweiten Umlauf hintendran. */

/* ---------------------------------------------------------------------------
   HELL UND DUNKEL STEHEN IN EINER ZEILE, NICHT IN ZWEI BLÖCKEN

   Bis vor Kurzem stand jede Farbe zweimal da: einmal hier, einmal in einem
   `@media (prefers-color-scheme: dark)`. Der Umschalter im Fuß hätte einen
   DRITTEN Satz gebraucht — drei Kopien derselben Palette, die auseinanderlaufen,
   sobald jemand eine Farbe ändert.

   `light-dark()` nimmt beide Werte in einer Zeile. Welcher gilt, entscheidet
   `color-scheme` am Wurzelelement:

     color-scheme: light dark   → wie das Betriebssystem (Vorgabe)
     color-scheme: light        → immer hell
     color-scheme: dark         → immer dunkel

   Nebenbei stellt `color-scheme` auch Rollbalken, Auswahlfelder und
   Datumsauswahl mit um — das tat die Medienabfrage nie.
   -------------------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  /* ---- Papier ---------------------------------------------------------- */
  --papier:      light-dark(#f3f0ea, #17150f);   /* Grundfläche */
  --papier-tief: light-dark(#e7e2d9, #100f0a);   /* vertieft, geprägt */
  --papier-hoch: light-dark(#fbf9f5, #23201a);   /* aufliegend */
  --karte:       light-dark(#fbf9f5, #201d17);

  /* ---- Tinte ----------------------------------------------------------- */
  --tinte:       light-dark(#17140f, #f4f1e8);   /* 16,15:1 auf Papier */
  --tinte-leise: light-dark(#6a6357, #a9a293);   /* zweiter Ordnung — 5,22:1 */
  --linie:       light-dark(#ded8cc, #322e26);
  --linie-stark: light-dark(#c6bfae, #4b4539);

  /* ---- Akzent ----------------------------------------------------------
     Rund zwei Prozent der Fläche. Fokusring, aktiver Weg, Fortschritt,
     Pflichthinweise. Mehr nicht — sonst ist es kein Akzent mehr. */
  --akzent:      light-dark(#9b3a1e, #e07a53);
  --akzent-hell: light-dark(#f6ece7, #2b1a12);

  --gut:         light-dark(#2f6b45, #78c79a);
  --gut-hell:    light-dark(#ecf3ee, #16241b);
  --schlecht:    light-dark(#a4232a, #f0868c);
  --schlecht-hell: light-dark(#fbeeee, #2a1618);
  --warnung:     light-dark(#8a5a00, #e0b155);
  --warnung-hell: light-dark(#fbf3e2, #2a2214);

  /* ---- Licht -----------------------------------------------------------
     Fest, nicht dem Zeiger folgend. Oben links, wie eine Fensterfront. */
  --lx: -0.42;
  --ly: -0.90;
  --licht: 0.55;

  --radius:       12px;
  --radius-klein: 8px;

  /* Aufliegend: ein feiner Rand plus weicher Schlagschatten.

     Die Abstände sind in beiden Themen gleich — nur die Farben wechseln. Genau
     dafür steht `light-dark()` hier mitten im Schattenwert: Ein zweiter
     kompletter Schattensatz für Dunkel wäre dieselbe Geometrie noch einmal. */
  --schatten:
    0 1px 1px         light-dark(rgba(52, 44, 30, .05), rgba(0, 0, 0, .50)),
    0 10px 26px -18px light-dark(rgba(52, 44, 30, .30), rgba(0, 0, 0, .80)),
    inset 0 1px 0     light-dark(rgba(255, 255, 255, .8), rgba(255, 255, 255, .05));

  /* Dasselbe, nur weiter vom Papier abgehoben — beim Überfahren einer Kachel. */
  --schatten-hoch:
    0 1px 1px         light-dark(rgba(52, 44, 30, .05), rgba(0, 0, 0, .50)),
    0 18px 34px -20px light-dark(rgba(52, 44, 30, .38), rgba(0, 0, 0, .90)),
    inset 0 1px 0     light-dark(rgba(255, 255, 255, .8), rgba(255, 255, 255, .07));

  /* Hineingeprägt: zwei gegenläufige Innenschatten entlang der Lichtachse. */
  --praegung:
    inset calc(var(--lx) * 2px) calc(var(--ly) * 2px) 5px
      light-dark(rgba(52, 44, 30, .11), rgba(0, 0, 0, .55)),
    inset calc(var(--lx) * -1px) calc(var(--ly) * -1px) 0
      light-dark(rgba(255, 253, 247, .9), rgba(255, 250, 240, .06));

  --schrift-display: "Instrument Serif", "Iowan Old Style", Georgia, serif;
  --schrift:         "Schibsted Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --schrift-code:    "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

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

/* Die Wahl aus dem Fuß. `_rahmen.php` schreibt sie aus dem Cookie schon in die
   erste Zeile der Antwort — deshalb blitzt beim Laden nichts in der falschen
   Farbe auf. Ohne Attribut (oder mit „system") gilt die Zeile oben. */
:root[data-thema="hell"]   { color-scheme: light; }
:root[data-thema="dunkel"] { color-scheme: dark; }

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--papier);
  color: var(--tinte);
  font: 400 16px/1.6 var(--schrift);
  font-feature-settings: "kern" 1;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* Papierfaser. Ein einziges Rauschmuster als data:-URI, über alles gelegt.
   Sehr zurückhaltend — es soll man spüren, nicht sehen. */
body::before {
  content: "";
  position: fixed;
  inset: -10%;
  z-index: 0;
  pointer-events: none;
  opacity: .30;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  background-size: 220px 220px;
}
/* Die einzige Stelle, die `light-dark()` NICHT abdeckt: Blendmodus und
   Deckkraft sind keine Farbwerte. Deshalb steht sie doppelt da — einmal für
   das Betriebssystem, einmal für die ausdrückliche Wahl. */
@media (prefers-color-scheme: dark) {
  :root:not([data-thema="hell"]) body::before { mix-blend-mode: screen; opacity: .05; }
}
:root[data-thema="dunkel"] body::before { mix-blend-mode: screen; opacity: .05; }

/* Alles Bedienbare liegt über der Faser. */
.kopf, .shell, .fuss { position: relative; z-index: 1; }

/* ---------------------------------------------------------------------------
   Schrift
   -------------------------------------------------------------------------- */

h1 {
  font-family: var(--schrift-display);
  font-weight: 400;
  font-size: clamp(1.9rem, 1.5rem + 1.4vw, 2.6rem);
  line-height: 1.1;
  letter-spacing: -.005em;
  margin: 0 0 .8rem;
}
h2 {
  font-family: var(--schrift-display);
  font-weight: 400;
  font-size: clamp(1.3rem, 1.15rem + .5vw, 1.55rem);
  line-height: 1.2;
  margin: 0 0 .7rem;
}
h3 {
  font-size: .8125rem;
  font-family: var(--schrift-code);
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--tinte-leise);
  margin: 1.8rem 0 .7rem;
}
p { margin: 0 0 .9rem; }

a { color: var(--tinte); text-decoration-color: var(--linie-stark); text-underline-offset: 3px; }
a:hover { text-decoration-color: var(--akzent); color: var(--akzent); }

code, pre { font-family: var(--schrift-code); font-size: .8125em; }
pre { overflow-x: auto; }

/* Tastaturbedienung muss sichtbar sein — sonst ist sie unbenutzbar.
   Ohne border-radius: Der Rahmen folgt von sich aus der Rundung des Elements.
   Einen eigenen Wert zu setzen würde eine Pillenform beim Fokussieren
   quadratisch machen. */
:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: 2px;
}

.muted { color: var(--tinte-leise); }
.klein { font-size: .875rem; }
.warn  { color: var(--schlecht); }
.ist-gut { color: var(--gut); }
.ist-warnung { color: var(--schlecht); }
.rechts { text-align: right; }
.nowrap { white-space: nowrap; }
.bruch { overflow-wrap: anywhere; }

/* ---------------------------------------------------------------------------
   Aufbau
   -------------------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: 70rem;
  margin: 0 auto;
  padding: 2.25rem 1.25rem 4rem;
  flex: 1;
}
.shell--schmal { max-width: 34rem; }

.spalten { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
@media (min-width: 62rem) {
  .spalten { grid-template-columns: 1fr 1fr; align-items: start; }
  .spalten--breit-schmal { grid-template-columns: 3fr 2fr; }
}

/* ---- Banner der Kundenansicht ---------------------------------------- */

/* Die einzige Fläche im Portal, die durchgehend in der Akzentfarbe steht.
   Genau deshalb funktioniert sie: Wo sonst nirgends Farbe ist, sieht man sie. */
.ansichtsbanner {
  position: relative; z-index: 11;
  background: var(--akzent);
  color: var(--papier);
  font-family: var(--schrift-code); font-size: .8125rem; letter-spacing: .02em;
}
.ansichtsbanner__innen {
  max-width: 70rem; margin: 0 auto; padding: .5rem 1.25rem;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
}
.ansichtsbanner__text strong { font-weight: 700; }
.ansichtsbanner__text .klein { opacity: .8; }
.ansichtsbanner form { margin: 0; }
.ansichtsbanner .knopf {
  background: transparent; color: var(--papier);
  border-color: color-mix(in srgb, var(--papier) 55%, transparent);
  box-shadow: none;
}
.ansichtsbanner .knopf:hover {
  background: color-mix(in srgb, var(--papier) 15%, transparent);
  border-color: var(--papier); transform: none;
}
.ansichtsbanner .knopf:focus-visible { outline-color: var(--papier); }

/* ---- Kopfleiste ------------------------------------------------------ */

.kopf {
  /* Deckende Farbe zuerst: Wer color-mix() nicht kennt (Safari vor 16.2),
     verwirft die zweite Zeile und behält eine Kopfleiste, durch die man beim
     Scrollen nicht hindurchsieht. */
  background: var(--papier);
  background: color-mix(in srgb, var(--papier) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--linie);
  position: sticky; top: 0; z-index: 10;
}
.kopf__innen {
  max-width: 70rem; margin: 0 auto; padding: .6rem 1.25rem;
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
}

/* Die Marke: das VR-Zeichen der Studio-Webseite, daneben der Wortlaut. */
.kopf__marke {
  display: inline-flex; align-items: center; gap: .6rem;
  text-decoration: none; color: var(--tinte);
  font-family: var(--schrift-code); font-weight: 500;
  font-size: .875rem; letter-spacing: .02em;
}
.kopf__marke:hover { color: var(--tinte); }
.kopf__marke span { color: var(--tinte-leise); }

/* Das Zeichen aus _marke.php. `currentColor`, damit es überall die Farbe
   seiner Umgebung annimmt — auch im Dunkelmodus. */
.zeichen { display: block; width: 26px; height: auto; fill: currentColor; flex: 0 0 auto; }

.kopf__nav { display: flex; gap: .15rem; margin-left: auto; flex-wrap: wrap; }
.kopf__nav a {
  text-decoration: none;
  padding: .45rem .8rem;
  border-radius: 99px;
  font-family: var(--schrift-code);
  font-size: .8125rem;
  color: var(--tinte-leise);
  transition: background .15s var(--weich), color .15s var(--weich);
}
.kopf__nav a:hover { background: var(--papier-tief); color: var(--tinte); }
.kopf__nav .ist-studio { color: var(--tinte); }

.kopf__konto { display: flex; align-items: center; gap: .5rem; font-size: .875rem; }
.kopf__konto a { color: var(--tinte-leise); text-decoration: none; }
.kopf__konto form { margin: 0; }

.fuss {
  border-top: 1px solid var(--linie);
  padding: 1.5rem 1.25rem; text-align: center;
  font-family: var(--schrift-code);
  font-size: .75rem; letter-spacing: .04em; color: var(--tinte-leise);
}
.fuss p { margin: .2rem 0; }

/* Der Farbumschalter im Fuß. Ausgeblendet, bis das Skript ihn übernimmt —
   ohne JavaScript täte er nichts, und die Anpassung ans Betriebssystem läuft
   ohnehin weiter. */
.themawahl { display: none; gap: .3rem; justify-content: center; margin-bottom: .9rem; }
.themawahl.ist-schaltbar { display: inline-flex; }
.themawahl button {
  padding: .3rem .7rem; border: 0; border-radius: 99px; cursor: pointer;
  font-family: var(--schrift-code); font-size: .6875rem; letter-spacing: .05em;
  color: var(--tinte-leise); background: var(--papier-tief);
  transition: color .15s var(--weich), background .15s var(--weich);
}
.themawahl button:hover { color: var(--tinte); background: var(--akzent-hell); }
.themawahl button.ist-aktuell { color: var(--papier); background: var(--tinte); }

/* Auf den abgemeldeten Seiten steht der Fuß auf dem dunklen Bild — dort
   gelten die Papierfarben nicht. Über den Geschwisterwähler, nicht über
   `:has()`: Der Fuß folgt im Markup direkt auf die Fläche, das genügt. */
.anmelde ~ .fuss { color: rgba(252, 248, 240, .62); border-top-color: rgba(255, 255, 255, .12); }
.anmelde ~ .fuss .muted { color: rgba(252, 248, 240, .52); }
.anmelde ~ .fuss .themawahl button {
  color: rgba(252, 248, 240, .70); background: rgba(255, 255, 255, .10);
}
.anmelde ~ .fuss .themawahl button:hover {
  color: rgba(255, 252, 246, .95); background: rgba(255, 255, 255, .18);
}
.anmelde ~ .fuss .themawahl button.ist-aktuell {
  color: #17140f; background: rgba(252, 248, 240, .88);
}

.brotkrumen {
  font-family: var(--schrift-code); font-size: .75rem; letter-spacing: .04em;
  color: var(--tinte-leise); margin-bottom: 1rem;
}
.brotkrumen a { color: var(--tinte-leise); text-decoration: none; }
.brotkrumen a:hover { color: var(--akzent); }
.brotkrumen span { margin: 0 .4rem; opacity: .5; }

.seiten-kopf {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1.25rem;
}
.seiten-kopf h1, .seiten-kopf h2 { margin: 0; }
.seiten-kopf__knoepfe { display: flex; gap: .5rem; flex-wrap: wrap; }

/* ---------------------------------------------------------------------------
   Karten — aufliegend auf dem Papier
   -------------------------------------------------------------------------- */

.karte, .gruppe, .kachel, .tabelle-rahmen {
  background: linear-gradient(175deg, var(--papier-hoch), var(--karte));
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  box-shadow: var(--schatten);
}
.karte, .gruppe { padding: 1.4rem; margin-bottom: 1.25rem; }
.karte > :last-child, .gruppe > :last-child { margin-bottom: 0; }
.karte h3:first-child, .gruppe h3:first-child { margin-top: 0; }

.karte--anmeldung { padding: 2rem; }
.karte--anmeldung h1 { font-size: clamp(1.7rem, 1.4rem + 1vw, 2.1rem); }
.karte--anmeldung .knopf--voll { margin-top: .3rem; }
.karte--anmeldung details,
.karte--anmeldung > form.klein { margin-top: 1.2rem; }
.karte--warnung { border-color: var(--warnung); background: var(--warnung-hell); }

/* ---------------------------------------------------------------------------
   Die abgemeldeten Seiten liegen auf dem Studio

   Anmelden, Codeabfrage und die beiden Einladungsschritte teilen sich diese
   Fläche. Ein Kunde sieht sie als Erstes vom Portal.

   Das Bild ist bereits verwischt und abgedunkelt ausgeliefert
   (`tools/hintergrund.php`, 59 kB) — kein `filter: blur()` im Browser, das
   müsste bei jedem Aufbau neu gerechnet werden und ließe an den Rändern
   durchsichtige Säume stehen.

   Der Schleier darüber liegt dagegen HIER und nicht in der Datei: Eine
   einfarbige Decke kostet nichts und lässt sich nachstellen, ohne ein neues
   Bild zu erzeugen.
   -------------------------------------------------------------------------- */

.anmelde { max-width: 30rem; }

.anmelde::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(160deg, rgba(12, 9, 6, .58), rgba(12, 9, 6, .78)),
    url("/assets/img/anmelden-hintergrund.jpg?v=1");
  background-size: cover;
  background-position: center;
}

/* Auf dem dunklen Bild ist `--tinte-leise` im hellen Thema unlesbar. Der
   Schriftzug bekommt deshalb eine feste helle Farbe — er steht ja immer auf
   dem Bild, nie auf Papier. */
.anmelde .anmelde-marke { color: rgba(252, 248, 240, .74); }
.anmelde .anmelde-marke .zeichen { color: rgba(252, 248, 240, .92); }

/* Im dunklen Thema ist die Karte selbst dunkel und würde auf dem dunklen Bild
   verschwimmen. Ein kräftigerer Schlagschatten hebt sie wieder ab. */
.anmelde .karte--anmeldung {
  box-shadow:
    0 30px 70px -28px rgba(0, 0, 0, .75),
    var(--schatten);
}

/* Die Anmeldeseite trägt keine Kopfleiste. Das Zeichen steht deshalb über
   der Karte — sonst wäre die erste Seite, die ein Kunde zu sehen bekommt,
   ohne Absender. */
.anmelde-marke {
  display: flex; align-items: center; justify-content: center; gap: .6rem;
  margin: min(8vh, 3.5rem) 0 1.5rem;
  font-family: var(--schrift-code); font-size: .8125rem;
  letter-spacing: .04em; color: var(--tinte-leise);
}
.anmelde-marke .zeichen { width: 30px; color: var(--tinte); }

/* Leerer Zustand. Kein „keine Einträge" in einer Tabellenzeile, sondern eine
   Fläche mit Platz — dort steht meistens, was als Nächstes zu tun ist. */
.leer { text-align: center; padding: 3.5rem 1.5rem; }
.leer h2 { margin-bottom: .5rem; }
.leer p { color: var(--tinte-leise); max-width: 34rem; margin-left: auto; margin-right: auto; }
.leer .knopfreihe { justify-content: center; margin-top: 1.2rem; }

.kacheln { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 44rem) {
  .kacheln { grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); }
  /* Kundenkacheln tragen mehr: Leistungen, Seiten, Zahlen, Balken. Unter
     26rem quetscht sich das, deshalb eine eigene Untergrenze. */
  .kacheln--breit { grid-template-columns: repeat(auto-fill, minmax(26rem, 1fr)); }
}
.kachel {
  padding: 1.4rem;
  transition: transform .2s var(--weich), box-shadow .2s var(--weich);
}
.kachel:hover { transform: translateY(-2px); box-shadow: var(--schatten-hoch); }
.kachel h2, .kachel h3 { margin: 0 0 .5rem; }
.kachel h3 { font-family: var(--schrift-display); font-size: 1.2rem;
             text-transform: none; letter-spacing: 0; color: var(--tinte); }
.kachel h2 a, .kachel h3 a { text-decoration: none; }
.kachel__daten { margin: .9rem 0; font-size: .875rem; }
.kachel__daten div {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: .3rem 0; border-bottom: 1px solid var(--linie);
}
.kachel__daten div:last-child { border-bottom: none; }
.kachel__daten dt { color: var(--tinte-leise); margin: 0; }
.kachel__daten dd { margin: 0; text-align: right; }
.kachel__knoepfe { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: 1rem; }

/* ---- Kundenkachel auf der Studio-Startseite ---- */

.kunde__kopf {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .8rem; margin-bottom: .6rem;
}
.kunde__kopf h2 { margin: 0; font-size: 1.25rem; }
.kunde__kopf h2 a { text-decoration: none; }

.kunde__leistungen { display: flex; gap: .35rem; flex-wrap: wrap; margin-bottom: .9rem; }

.kunde__seiten { list-style: none; margin: 0 0 .9rem; padding: 0; font-size: .875rem; }
.kunde__seiten li {
  display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
  padding: .35rem 0; border-bottom: 1px solid var(--linie);
}
.kunde__seiten li:last-child { border-bottom: none; }

/* Zwischenüberschrift in einer Tabelle — trennt die Rollen in der Kontenliste. */
.gruppenzeile th {
  background: var(--papier-tief);
  border-top: 1px solid var(--linie-stark);
  font-family: var(--schrift-code); font-size: .6875rem; font-weight: 500;
  letter-spacing: .09em; text-transform: uppercase; color: var(--tinte-leise);
  padding: .5rem .9rem;
}

.hinweis-stand {
  background: var(--warnung-hell); color: var(--warnung);
  border-radius: var(--radius-klein); padding: .55rem .8rem;
  font-size: .875rem; margin-bottom: 1rem;
}

/* ---------------------------------------------------------------------------
   Knöpfe
   -------------------------------------------------------------------------- */

.knopf {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  /* 44 px Mindesthöhe: kleiner lässt sich am Handy nicht zuverlässig treffen. */
  min-height: 44px;
  padding: .55rem 1.1rem;
  border: 1px solid var(--linie-stark);
  border-radius: 99px;
  background: linear-gradient(175deg, var(--papier-hoch), var(--karte));
  color: var(--tinte);
  font: inherit; font-size: .9375rem; font-weight: 500;
  text-decoration: none; cursor: pointer;
  box-shadow: 0 1px 1px rgba(52, 44, 30, .04);
  transition: transform .12s var(--weich), box-shadow .15s var(--weich),
              background .15s var(--weich), border-color .15s var(--weich);
}
.knopf:hover { border-color: var(--tinte-leise); transform: translateY(-1px);
               box-shadow: 0 4px 12px -6px rgba(52, 44, 30, .35); }
.knopf:active { transform: translateY(0); box-shadow: var(--praegung); }
.knopf:disabled { opacity: .45; cursor: not-allowed; transform: none; }

.knopf--stark {
  background: var(--tinte); color: var(--papier); border-color: var(--tinte);
}
.knopf--stark:hover { background: var(--tinte); opacity: .9; }

/* Schrift in Papierfarbe statt Weiß: Im Dunkelmodus ist `--gut` ein helles
   Grün, auf dem Weiß nicht mehr lesbar wäre. `--papier` kippt mit. */
.knopf--gruen { background: var(--gut); color: var(--papier); border-color: var(--gut); }
.knopf--gruen:hover { background: var(--gut); opacity: .9; }

.knopf--weg { color: var(--schlecht); border-color: color-mix(in srgb, var(--schlecht) 45%, transparent);
              background: transparent; box-shadow: none; }
.knopf--weg:hover { background: var(--schlecht-hell); border-color: var(--schlecht); }

.knopf--leise { background: transparent; border-color: var(--linie); box-shadow: none; }
.knopf--leise:hover { background: var(--papier-tief); }

.knopf--klein { min-height: 36px; padding: .3rem .75rem; font-size: .8125rem; }
.knopf--voll { width: 100%; }

.knopfreihe { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
.knopfreihe form { margin: 0; }

/* ---------------------------------------------------------------------------
   Formulare — Felder sind ins Papier geprägt
   -------------------------------------------------------------------------- */

.formular { margin: 0; }
.formular--reihe { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
.formular--reihe input, .formular--reihe select { flex: 1 1 12rem; }

/* Der Seiteneditor. Etwas mehr Luft zwischen den Gruppen als sonst — es sind
   viele, und man arbeitet sie von oben nach unten ab. */
.formular--editor .gruppe { margin-bottom: 1.75rem; }

.feld { margin-bottom: 1.1rem; }

/* Beschriftungen bewusst OHNE Versalien und in der Fließschrift, anders als
   Überschriften, Tabellenköpfe und Marken. Grund: Sie sind hier oft ganze
   Fragen — „Was ist auf dem Bild zu sehen?", „Was besonders hervorgehoben
   werden soll". In Großbuchstaben liest das niemand gern, und ein Fragezeichen
   hinter einer Versalzeile sieht aus wie ein Fehler.
   Volle Tintenfarbe statt der leisen: Die Beschriftung sagt, was einzutragen
   ist — sie ist nicht die Nebensache im Feld. */
.feld label {
  display: block; font-weight: 500; font-size: .9375rem;
  color: var(--tinte); margin-bottom: .4rem;
}
.feld__frei { font-weight: 400; color: var(--tinte-leise); font-size: .875rem; }
.feld__sub  { display: block; font-size: .8125rem; color: var(--tinte-leise); margin-top: .4rem; }

input[type=text], input[type=email], input[type=password], input[type=url],
input[type=tel], input[type=time], input[type=date], input[type=number],
input[type=file], select, textarea {
  width: 100%;
  padding: .6rem .8rem;
  min-height: 44px;
  border: 1px solid var(--linie-stark);
  border-radius: var(--radius-klein);
  background: var(--papier-tief);
  color: var(--tinte);
  box-shadow: var(--praegung);
  /* 16 px verhindert, dass iOS beim Antippen hineinzoomt. */
  font: inherit; font-size: 16px;
  transition: border-color .15s var(--weich), background .15s var(--weich);
}
textarea { min-height: 5.5rem; resize: vertical; line-height: 1.55; }
input:hover, select:hover, textarea:hover { border-color: var(--tinte-leise); }
input:focus, select:focus, textarea:focus {
  border-color: var(--akzent);
  background: var(--karte);
  outline-offset: 1px;
}
input::placeholder, textarea::placeholder { color: var(--tinte-leise); opacity: .6; }

.eingabe--code {
  font-family: var(--schrift-code); font-size: 1.6rem; font-weight: 500;
  letter-spacing: .32em; text-align: center; text-indent: .32em;
}
/* Der Einladungscode hat 19 Zeichen statt sechs — mit der Sperrung von oben
   liefe er aus dem Feld. */
.eingabe--code-lang {
  font-size: 1.05rem; letter-spacing: .14em; text-indent: .14em;
}
textarea.code { font-family: var(--schrift-code); font-size: .8125rem; line-height: 1.55; }
pre.code {
  background: var(--papier-tief); border: 1px solid var(--linie);
  border-radius: var(--radius-klein); padding: .9rem; margin: 0 0 .9rem;
  box-shadow: var(--praegung);
}

/* Die Aktionsleiste klebt unten — beim langen Formular soll „Speichern"
   erreichbar bleiben, ohne ans Ende zu rollen. */
.leiste {
  position: sticky; bottom: 0;
  display: flex; gap: .6rem; flex-wrap: wrap; align-items: center;
  background: var(--karte);
  background: color-mix(in srgb, var(--karte) 92%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border: 1px solid var(--linie); border-radius: var(--radius);
  padding: .85rem 1.1rem; margin-top: 1.5rem;
  box-shadow: 0 -4px 22px -12px rgba(52, 44, 30, .4);
}
.leiste__hinweis { margin-left: auto; }

/* ---------------------------------------------------------------------------
   Gruppen und Listen
   -------------------------------------------------------------------------- */

.gruppe__hinweis { font-size: .875rem; color: var(--tinte-leise); margin-bottom: 1.1rem; }

/* Eine Gruppe, in der wiederholbare Einträge stehen. Der Streifen am linken
   Rand sagt: hier sind es mehrere, und es können mehr werden. */
.gruppe--liste { border-left: 3px solid var(--linie-stark); }

.liste__zeilen { display: flex; flex-direction: column; gap: .8rem; margin-bottom: .8rem; }

.liste__zeile {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .6rem;
  padding: .9rem;
  background: var(--papier-tief);
  border: 1px solid var(--linie);
  border-radius: var(--radius-klein);
  box-shadow: var(--praegung);
}
.liste__griff { color: var(--linie-stark); font-size: 1.1rem; line-height: 1.6; user-select: none; cursor: grab; }
.liste__felder { display: grid; gap: .6rem; }
@media (min-width: 40rem) {
  .liste__felder { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
}
.liste__felder .feld { margin-bottom: 0; }
.liste__aktionen { grid-column: 1 / -1; display: flex; gap: .35rem; justify-content: flex-end; }
.liste__leer { color: var(--tinte-leise); font-size: .875rem; }
.liste__zaehler { margin-left: .6rem; }

/* ---------------------------------------------------------------------------
   Meldungen und Marken
   -------------------------------------------------------------------------- */

.meldung {
  border-radius: var(--radius-klein);
  padding: .9rem 1.1rem;
  margin-bottom: 1.25rem;
  border: 1px solid;
  border-left-width: 3px;
  font-size: .9375rem;
}
.meldung p:last-child { margin-bottom: 0; }
.meldung--gut    { background: var(--gut-hell);      border-color: var(--gut);      color: var(--gut); }
.meldung--fehler { background: var(--schlecht-hell); border-color: var(--schlecht); color: var(--schlecht); }
.meldung--warn   { background: var(--warnung-hell);  border-color: var(--warnung);  color: var(--warnung); }
.meldung a { color: inherit; }
.meldung__liste { margin: .5rem 0 0; padding-left: 1.2rem; font-size: .875rem; }

.marke {
  display: inline-block;
  font-family: var(--schrift-code);
  font-size: .6875rem; font-weight: 500; letter-spacing: .04em;
  padding: .15rem .55rem; border-radius: 99px; white-space: nowrap;
  vertical-align: middle;
}
.marke--gut      { background: var(--gut-hell);      color: var(--gut); }
.marke--schlecht { background: var(--schlecht-hell); color: var(--schlecht); }
.marke--grau     { background: var(--papier-tief);   color: var(--tinte-leise); }

/* ---------------------------------------------------------------------------
   Tabellen
   -------------------------------------------------------------------------- */

/* Breite Tabellen rollen in ihrem eigenen Rahmen — die Seite selbst darf
   niemals seitlich rollen. */
.tabelle-rahmen { overflow-x: auto; margin-bottom: 1.25rem; }
.tabelle { width: 100%; border-collapse: collapse; font-size: .9375rem; }
.tabelle th, .tabelle td {
  padding: .75rem .9rem; text-align: left; border-bottom: 1px solid var(--linie);
  vertical-align: top;
}
.tabelle th {
  font-family: var(--schrift-code);
  font-size: .6875rem; font-weight: 500; letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--tinte-leise); white-space: nowrap;
  background: var(--papier-tief);
}
.tabelle tr:last-child td { border-bottom: none; }
.tabelle tbody tr { transition: background .12s var(--weich); }
.tabelle tbody tr:hover { background: var(--papier-tief); }
.tabelle--klein { font-size: .875rem; }
.tabelle--klein td, .tabelle--klein th { padding: .45rem .6rem; }
.tabelle--dicht th, .tabelle--dicht td { padding: .4rem .6rem; font-size: .8125rem; }
.tabelle .ist-aktuell { background: var(--gut-hell); }
.tabelle .ist-gesperrt { opacity: .55; }
.tabelle td form { display: inline-block; margin: 0 0 0 .25rem; }
.tabelle td .muted.klein { display: block; }

/* Zahlen in Tabellen tabellarisch setzen, damit Spalten fluchten. */
.tabelle td { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   Listen und Kleinteile
   -------------------------------------------------------------------------- */

.daten { margin: 0; font-size: .9375rem; }
.daten div { display: flex; gap: 1rem; padding: .45rem 0; border-bottom: 1px solid var(--linie); }
.daten div:last-child { border-bottom: none; }
.daten dt { color: var(--tinte-leise); margin: 0; flex: 0 0 10rem;
            font-family: var(--schrift-code); font-size: .75rem;
            letter-spacing: .05em; text-transform: uppercase; padding-top: .18rem; }
.daten dd { margin: 0; flex: 1; }

.ablauf { margin: 0 0 .9rem; padding-left: 1.3rem; font-size: .9375rem; }
.ablauf li { margin-bottom: .45rem; }
.ablauf li::marker { color: var(--akzent); }

/* Wer sich meldet — Bild, Name, Nummer. Auf der Kontaktseite.
   Die Nummer ist bewusst so groß wie der Name: Sie ist der Zweck des
   Abschnitts, das Bild nur die Zuordnung dazu. */
.leute { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; }
.person {
  display: flex; align-items: center; gap: 1rem;
  padding: .8rem 0; border-bottom: 1px solid var(--linie);
}
.person:last-child { border-bottom: none; }
.person__bild {
  flex: 0 0 auto; width: 4.25rem; height: 4.25rem;
  border-radius: 50%; object-fit: cover;
  background: var(--papier-tief);
  box-shadow: var(--praegung);
}
.person__text { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.person__tel {
  font-family: var(--schrift-code); font-size: .9375rem;
  letter-spacing: .02em; margin-top: .2rem;
  text-decoration-color: var(--linie-stark);
}

.medien { list-style: none; margin: 0; padding: 0; }
.medium {
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  padding: .7rem 0; border-bottom: 1px solid var(--linie);
}
.medium:last-child { border-bottom: none; }
.medium__art {
  flex: 0 0 auto; font-family: var(--schrift-code);
  font-size: .625rem; font-weight: 500; letter-spacing: .08em;
  padding: .4rem .55rem; border-radius: var(--radius-klein);
  background: var(--papier-tief); color: var(--tinte-leise);
  box-shadow: var(--praegung);
}
/* Bild und PDF unterscheidbar machen — in einer langen Mediathek sucht man
   nach der Art, nicht nach dem Dateinamen. */
.medium__art--bild { color: var(--gut);    background: var(--gut-hell); }
.medium__art--pdf  { color: var(--akzent); background: var(--akzent-hell); }
.medium__text { flex: 1 1 14rem; min-width: 0; }
.medium__text strong { display: block; overflow-wrap: anywhere; }
.medium__text .klein { display: block; }
.medium__aktionen { display: flex; gap: .35rem; align-items: center; }
.medium__aktionen form { margin: 0; }

.sitzungen, .fassungen, .staende, .modellliste, .zugriffsliste, .codes, .notizen {
  list-style: none; margin: 0; padding: 0; font-size: .9375rem;
}
.sitzungen li, .fassungen li, .staende li, .modellliste li, .notizen li {
  padding: .65rem 0; border-bottom: 1px solid var(--linie);
}
.sitzungen li:last-child, .fassungen li:last-child, .staende li:last-child,
.modellliste li:last-child, .notizen li:last-child { border-bottom: none; }
.sitzung__browser { display: block; overflow-wrap: anywhere; font-size: .875rem; }
.notizen p { margin: 0 0 .3rem; }

.zugriffsliste li {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; padding: .6rem 0; border-bottom: 1px solid var(--linie);
}
.zugriffsliste li:last-child { border-bottom: none; }
.zugriffsliste form { margin: 0; }
.zugriffsliste .klein { display: block; }

.typenliste { margin: 0; font-size: .875rem; }
.typenliste div { display: flex; gap: .8rem; padding: .25rem 0; }
.typenliste dt { flex: 0 0 6.5rem; margin: 0; font-family: var(--schrift-code); }
.typenliste dd { margin: 0; color: var(--tinte-leise); }

/* Wiederherstellungscodes — groß und eindeutig, sie werden abgeschrieben. */
.codes {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: .5rem; margin: 1rem 0;
}
.codes li {
  background: var(--papier-tief); border: 1px solid var(--linie);
  border-radius: var(--radius-klein); padding: .55rem; text-align: center;
  box-shadow: var(--praegung);
}
.codes code { font-size: 1rem; letter-spacing: .04em; }

/* Der QR-Code bleibt auch im Dunkelmodus auf weißem Grund — ein invertierter
   QR-Code ist für viele Scanner unlesbar. Das weiße Feld ist zugleich die
   Ruhezone, ohne die kein Scanner die Suchmuster findet. */
.qr { margin: 0 0 1.2rem; display: flex; justify-content: center; }
.qr img {
  display: block; max-width: 100%; height: auto;
  background: #fff; padding: .5rem;
  border: 1px solid var(--linie); border-radius: var(--radius-klein);
  box-shadow: var(--schatten);
}

.geheimnis {
  background: var(--papier-tief); border: 1px solid var(--linie);
  border-radius: var(--radius-klein); padding: .8rem;
  overflow-wrap: anywhere; box-shadow: var(--praegung);
}
.geheimnis code { font-size: 1rem; letter-spacing: .08em; }
.otpauth { overflow-wrap: anywhere; }

.nachricht__kopf {
  display: flex; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; margin-bottom: .7rem;
}
.nachricht__kopf .klein { display: block; }
.nachricht__marken { display: flex; gap: .35rem; align-items: flex-start; flex-wrap: wrap; }
.nachricht__text {
  background: var(--papier-tief); border-radius: var(--radius-klein);
  padding: .9rem; overflow-wrap: anywhere; box-shadow: var(--praegung);
}
.nachricht__fuss { display: flex; gap: .5rem; flex-wrap: wrap; }
.nachricht__fuss form { margin: 0; }
.nachricht.ist-erledigt { opacity: .6; }

details { margin-bottom: .9rem; }
summary { cursor: pointer; padding: .35rem 0; font-size: .9375rem; }
summary::marker { color: var(--akzent); }

/* ---------------------------------------------------------------------------
   Kundenakte, Leistungen, KI
   -------------------------------------------------------------------------- */

/* Sprungmarken, keine Umschalter. Der Inhalt steht ohnehin untereinander —
   ausgeblendete Abschnitte wären ohne JavaScript nicht erreichbar, und die
   CSP dieses Portals lässt keins zu. */
.reiter {
  display: flex; gap: .35rem; flex-wrap: wrap;
  margin: 0 0 1.5rem; padding-bottom: .7rem;
  border-bottom: 1px solid var(--linie);
}
.reiter a {
  padding: .45rem .9rem; border-radius: 99px;
  font-family: var(--schrift-code); font-size: .75rem; letter-spacing: .04em;
  text-decoration: none; color: var(--tinte-leise);
  background: var(--papier-tief);
  transition: color .15s var(--weich), background .15s var(--weich);
}
.reiter a:hover { color: var(--tinte); background: var(--akzent-hell); }

/* Verbrauchsbalken. Reine Anzeige — die Zahl steht immer daneben im Text:
   ein Balken allein ist für niemanden mit Sehschwäche eine Auskunft. */
.balken {
  height: 8px; border-radius: 99px; overflow: hidden;
  background: var(--papier-tief);
  box-shadow: var(--praegung);
  margin: .6rem 0;
}
.balken__voll {
  height: 100%; width: 0; background: var(--akzent); border-radius: 99px;
}
.balken__voll--warn { background: var(--schlecht); }

/* Die Breite steht in einer Klasse, nicht in einem style-Attribut: Die CSP
   führt `style-src 'self'`, und das verwirft auch style-Attribute — der
   Balken bliebe sonst wortlos auf null. Stufen zu fünf Prozent, gesetzt von
   View::balkenKlasse(). */
.balken__voll--0   { width: 0; }
.balken__voll--5   { width: 5%; }
.balken__voll--10  { width: 10%; }
.balken__voll--15  { width: 15%; }
.balken__voll--20  { width: 20%; }
.balken__voll--25  { width: 25%; }
.balken__voll--30  { width: 30%; }
.balken__voll--35  { width: 35%; }
.balken__voll--40  { width: 40%; }
.balken__voll--45  { width: 45%; }
.balken__voll--50  { width: 50%; }
.balken__voll--55  { width: 55%; }
.balken__voll--60  { width: 60%; }
.balken__voll--65  { width: 65%; }
.balken__voll--70  { width: 70%; }
.balken__voll--75  { width: 75%; }
.balken__voll--80  { width: 80%; }
.balken__voll--85  { width: 85%; }
.balken__voll--90  { width: 90%; }
.balken__voll--95  { width: 95%; }
.balken__voll--100 { width: 100%; }

.leistung { padding: 1.1rem 0; border-bottom: 1px solid var(--linie); margin: 0; }
.leistung:last-of-type { border-bottom: none; }
.leistung__kopf {
  display: flex; gap: 1rem; align-items: flex-start;
  justify-content: space-between; flex-wrap: wrap;
}
.leistung__kopf > div { flex: 1 1 16rem; }
.leistung__detail {
  margin: .9rem 0; padding: .9rem;
  background: var(--papier-tief); border-radius: var(--radius-klein);
  box-shadow: var(--praegung);
}
.leistung__detail p { margin: 0 0 .5rem; }

.haken {
  display: flex; gap: .6rem; align-items: baseline;
  padding: .4rem 0; font-weight: 400; cursor: pointer;
}
.haken input { flex: 0 0 auto; width: 1.1rem; height: 1.1rem; accent-color: var(--akzent); }
.haken .klein { display: block; }
.haken--merken { align-items: flex-start; margin: 1rem 0; text-align: left; }
.haken--merken input { margin-top: .25rem; }

/* ---------------------------------------------------------------------------
   Ein KI-Werkzeug: Eingabe links, Ergebnis rechts

   Vorher stand die Seite auf `shell--schmal` und belegte auf einem großen
   Bildschirm ein Drittel. Bei einem Werkzeug, dessen Ergebnis ein langer Text
   ist, ist das der falsche Zuschnitt: Man füllt oben ein Formular aus und
   scrollt dann zu etwas, das man gleichzeitig sehen will.

   Dieselbe Aufteilung wie im Seiten-Editor — links wird gearbeitet, rechts
   steht, was dabei herauskommt. Solange nichts erzeugt wurde, steht dort die
   Hilfekarte; die Fläche ist also nie leer.
   -------------------------------------------------------------------------- */

.werkzeug { display: block; }

@media (min-width: 62rem) {
  .werkzeug {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 1.75rem;
    align-items: start;
  }
  /* Das Ergebnis bleibt stehen, während links durch ein langes Formular
     gescrollt wird. */
  .werkzeug__ergebnis { position: sticky; top: 4.5rem; }
}

/* Ergebnis eines KI-Werkzeugs. Textfeld statt formatiertem Text: der Kunde
   soll es herauskopieren können, und was ankommt, ist Text — kein HTML, das
   gerendert werden dürfte. */
.ergebnis {
  width: 100%; font-family: var(--schrift); font-size: .9375rem; line-height: 1.6;
  background: var(--papier-tief); box-shadow: var(--praegung);
  min-height: 18rem; resize: vertical;
}
@media (min-width: 62rem) {
  .ergebnis { height: calc(100vh - 22rem); min-height: 22rem; }
}

/* Der Knopf, während die KI arbeitet. Der Punkt wandert — eine Bewegung, die
   sagt „es läuft noch", ohne zu blinken. */
.knopf--arbeitet { opacity: 1; cursor: progress; }
.knopf--arbeitet::after {
  content: "";
  display: inline-block; width: .4em; height: .4em; margin-left: .55em;
  border-radius: 50%; background: currentColor;
  animation: knopfpuls 1.1s var(--weich) infinite;
  vertical-align: middle;
}
@keyframes knopfpuls {
  0%, 100% { opacity: .25; transform: translateX(-.25em); }
  50%      { opacity: 1;   transform: translateX(.25em); }
}
@media (prefers-reduced-motion: reduce) {
  .knopf--arbeitet::after { animation: none; opacity: .7; }
}

form.inline { display: inline-flex; gap: .3rem; align-items: center; margin: 0; }
select.klein { min-height: 36px; padding: .25rem .5rem; font-size: .8125rem; }

/* ---------------------------------------------------------------------------
   Der Editor: Bild links, Formular rechts

   Am Handy wären zwei Spalten je zu schmal zum Benutzen — und am Handy wird
   tatsächlich bearbeitet. Dort deshalb zwei Reiter, umgeschaltet über
   `data-zeigt` an der Hülle.

   DIE BÜHNE UND WARUM SIE VERKLEINERT

   Eine Kundenseite schaltet ihr Desktop-Layout meist erst ab etwa 1000 px
   Breite ein (Toscanablick: 1024 px). Eine Spalte im Portal ist selbst auf
   einem großen Bildschirm schmaler — die Vorschau zeigte deshalb immer die
   Handy-Fassung, egal wie groß der Monitor war.

   Gelöst wird das nicht durch mehr Breite allein, sondern durch Verkleinern:
   Der Rahmen ist in der Desktop-Ansicht fest 1280 px breit — die Seite darin
   sieht also einen Desktop-Bildschirm — und wird per `transform: scale()` auf
   die Breite der Bühne heruntergerechnet. Klicks treffen trotzdem, weil die
   Trefferprüfung des Browsers mitskaliert.

   DER FAKTOR STEHT IN EINER KLASSE, NICHT IN EINEM style-ATTRIBUT

   Aus demselben Grund wie beim Verbrauchsbalken: Die CSP führt
   `style-src 'self'`, und das verwirft auch style-Attribute. Das Skript misst
   die Bühne und setzt eine der Stufenklassen unten — Klassen sind unbedenklich.
   Stufen zu 2,5 %; der Rest wird mittig ausgeglichen und ist nicht zu sehen.

   OHNE JAVASCRIPT

   Dann fehlen `.ist-gemessen` und die Stufenklasse, und es bleibt bei
   `width: 100%` — genau das Verhalten von vorher. Die Umschalter sind dann
   ausgeblendet, weil sie nichts täten.
   -------------------------------------------------------------------------- */

/* Wechsel zwischen den Webseiten eines Zugangs, über der Überschrift.
   Verweise, keine Knöpfe: Es sind Seitenwechsel, und ohne JavaScript sollen
   sie genauso gehen. */
.seitenwahl {
  display: flex; gap: .35rem; flex-wrap: wrap;
  margin: 0 0 1.1rem;
}
.seitenwahl a {
  padding: .35rem .8rem; border-radius: 99px;
  font-family: var(--schrift-code); font-size: .75rem; letter-spacing: .04em;
  text-decoration: none; color: var(--tinte-leise);
  background: var(--papier-tief);
  transition: color .15s var(--weich), background .15s var(--weich);
}
.seitenwahl a:hover { color: var(--tinte); background: var(--akzent-hell); }
.seitenwahl a.ist-aktuell { color: var(--papier); background: var(--tinte); }
.seitenwahl__viele { margin: 0 0 1.1rem; }

.editor { display: block; }
.reiter--editor { display: flex; }

/* Ohne Vorlage bleibt alles wie vorher: einspaltig, keine Reiter. */
.editor:not(.editor--geteilt) .reiter--editor,
.editor:not(.editor--geteilt) .editor__bild { display: none; }

/* Knöpfe beider Leisten — Reiter am Handy und Gerätewahl über der Bühne. */
.reiter--editor button,
.geraetewahl button {
  padding: .4rem .85rem; border: 0; border-radius: 99px; cursor: pointer;
  font-family: var(--schrift-code); font-size: .75rem; letter-spacing: .04em;
  color: var(--tinte-leise); background: var(--papier-tief);
  box-shadow: var(--praegung);
  transition: color .15s var(--weich), background .15s var(--weich);
}
.reiter--editor button:hover,
.geraetewahl button:hover { color: var(--tinte); background: var(--akzent-hell); }
.reiter--editor button.ist-aktuell,
.geraetewahl button.ist-aktuell {
  color: var(--papier); background: var(--tinte); box-shadow: none;
}

.editor__bild {
  position: relative;
  margin-bottom: 1.25rem;
}
.editor__bild-kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: .5rem;
}
.editor__bild-werkzeuge { display: flex; align-items: center; gap: .6rem; }
.editor__bild-fuss { margin: .6rem 0 0; }

/* Erst wenn das Skript läuft, gibt es etwas zu schalten. */
.geraetewahl { display: none; gap: .3rem; }
.editor__bild--schaltbar .geraetewahl { display: inline-flex; }

.editor__buehne {
  position: relative; overflow: hidden;
  height: 78vh; min-height: 24rem;
  border: 1px solid var(--linie); border-radius: var(--radius);
  background: var(--papier-hoch);
  box-shadow: var(--schatten);
}
.editor__geraet {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
}
.editor__geraet-box { position: absolute; inset: 0; }
.editor__rahmen {
  position: absolute; top: 0; left: 0;
  display: block; width: 100%; height: 100%;
  border: 0; background: var(--papier-hoch);
}
.editor__geraet-bild { display: none; }

/* ---- Desktop-Ansicht: fest 1280 px, heruntergerechnet ---- */
.editor__bild[data-geraet="desktop"] .editor__buehne.ist-gemessen .editor__rahmen {
  width: 1280px;
  height: calc(100% / var(--f, 1));
  left: calc((100% - (1280px * var(--f, 1))) / 2);
  transform: scale(var(--f, 1));
  transform-origin: top left;
}

/* ---------------------------------------------------------------------------
   Handy-Ansicht: die Seite steckt in einem Telefon

   Das Gehäusebild liegt ÜBER der Vorschau und ist `pointer-events: none` —
   Rand und Ecken decken die Seite ab wie bei einem echten Telefon, Klicks
   gehen hindurch ins Feld.

   DIE ZAHLEN SIND GEMESSEN, NICHT GESCHÄTZT

   Wo im Bild der Bildschirm sitzt, hat `tools/geraeterahmen.php` ermittelt und
   als Prozentwerte ausgegeben. Wird der Rahmen je neu erzeugt, liefert das
   Werkzeug den Block hier fertig zum Austauschen. Von Hand abgemessene Werte
   wären beim nächsten Bild wieder falsch.

     Bild            701 x 1443
     Bildschirm      88,017 % breit, 94,456 % hoch, links 6,134 %, oben 2,841 %
     Eckenrundung    11,5 % der Bildschirmbreite

   DIE KASTENGRÖSSE FOLGT AUS DER SOLLBREITE

   Der Bildschirm soll 393 px zeigen — die Punktbreite eines iPhone 15 Pro.
   Also ist der Kasten 393 / 0,88017 = 446,5 px breit und im Verhältnis des
   Bildes 919,1 px hoch. Verkleinert wird danach in einem Stück, mit denselben
   Stufenklassen wie die Desktop-Ansicht. Ohne diese feste Größe bekäme die
   Seite in einem kleinen Fenster einen 250-px-Bildschirm zu sehen, den es an
   keinem Telefon gibt.
   -------------------------------------------------------------------------- */

.editor__bild[data-geraet="handy"] .editor__geraet-box {
  position: relative; inset: auto;
  width: 446.5px; height: 919.1px;
  flex: 0 0 auto;
}
.editor__bild[data-geraet="handy"] .editor__buehne.ist-gemessen .editor__geraet-box {
  transform: scale(var(--f, 1));
  transform-origin: center center;
}
.editor__bild[data-geraet="handy"] .editor__geraet-bild {
  display: block;
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 2;
}
.editor__bild[data-geraet="handy"] .editor__rahmen {
  left:   6.134%;
  top:    2.841%;
  width:  88.017%;
  height: 94.456%;
  /* Der Bildschirm ist rund; ohne das schauten die geraden Ecken der Seite
     unter dem Gehäuse hervor. Auch dieser Wert ist gemessen — 11,5 % der
     Bildschirmbreite, bei 393 px also 45. */
  border-radius: 45px;
}

/* Stufen des Verkleinerungsfaktors, in Promille. Gesetzt von vorschau.js,
   das immer abrundet — lieber ein Fingerbreit Luft als ein abgeschnittener
   Rand. */
.editor__buehne--z250  { --f: .250; }
.editor__buehne--z275  { --f: .275; }
.editor__buehne--z300  { --f: .300; }
.editor__buehne--z325  { --f: .325; }
.editor__buehne--z350  { --f: .350; }
.editor__buehne--z375  { --f: .375; }
.editor__buehne--z400  { --f: .400; }
.editor__buehne--z425  { --f: .425; }
.editor__buehne--z450  { --f: .450; }
.editor__buehne--z475  { --f: .475; }
.editor__buehne--z500  { --f: .500; }
.editor__buehne--z525  { --f: .525; }
.editor__buehne--z550  { --f: .550; }
.editor__buehne--z575  { --f: .575; }
.editor__buehne--z600  { --f: .600; }
.editor__buehne--z625  { --f: .625; }
.editor__buehne--z650  { --f: .650; }
.editor__buehne--z675  { --f: .675; }
.editor__buehne--z700  { --f: .700; }
.editor__buehne--z725  { --f: .725; }
.editor__buehne--z750  { --f: .750; }
.editor__buehne--z775  { --f: .775; }
.editor__buehne--z800  { --f: .800; }
.editor__buehne--z825  { --f: .825; }
.editor__buehne--z850  { --f: .850; }
.editor__buehne--z875  { --f: .875; }
.editor__buehne--z900  { --f: .900; }
.editor__buehne--z925  { --f: .925; }
.editor__buehne--z950  { --f: .950; }
.editor__buehne--z975  { --f: .975; }
.editor__buehne--z1000 { --f: 1; }

/* ---- Am Handy: Reiter ---- */
@media (max-width: 61.99rem) {
  .editor--geteilt[data-zeigt="bearbeiten"] .editor__bild     { display: none; }
  .editor--geteilt[data-zeigt="vorschau"]  .editor__formular  { display: none; }
}

/* ---- Ab Tablet: nebeneinander ---- */
@media (min-width: 62rem) {
  .editor--geteilt {
    display: grid;
    /* Die Vorschau bekommt mehr als die Hälfte: Das Formular ist eine Spalte
       aus Beschriftung und Eingabefeld und kommt mit weniger aus, die Seite
       nicht. */
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    gap: 1.5rem;
    align-items: start;
  }
  /* Die Reiter braucht es hier nicht — beide Hälften stehen ohnehin da. */
  .editor--geteilt .reiter--editor { display: none; }

  /* Das Bild bleibt stehen, während man rechts durch ein langes Formular
     scrollt. Sonst rollt man an der Stelle vorbei, die man gerade ändert. */
  .editor--geteilt .editor__bild { position: sticky; top: 4.5rem; }
  .editor--geteilt .editor__buehne { height: calc(100vh - 11rem); }
}

/* ---- Ab 78 rem: der Arbeitsbereich tritt aus der Seitenbreite heraus ----

   Überschrift, Kopfleiste und Fuß bleiben auf ihren 70 rem stehen — sonst
   stünde die Seite auf einem breiten Bildschirm auseinandergezogen da. Nur der
   geteilte Bereich nimmt sich die volle Breite; genau er braucht sie.

   `100vw` schließt die Bildlaufleiste mit ein, deshalb 3 rem Abzug statt
   2,5 rem: Der Rest ist Luft, damit die Seite nicht seitlich zu rollen
   beginnt. */
@media (min-width: 78rem) {
  .editor--geteilt {
    width: min(112rem, calc(100vw - 3rem));
    margin-left: calc(50% - min(56rem, calc(50vw - 1.5rem)));
  }
}

/* Das Feld, auf das gerade aus der Vorschau gesprungen wurde. */
.feld--getroffen > input,
.feld--getroffen > textarea,
.feld--getroffen > select {
  border-color: var(--akzent);
  box-shadow: var(--praegung), 0 0 0 3px var(--akzent-hell);
}

/* ---------------------------------------------------------------------------
   Hilfekarte mit Erklärbild
   -------------------------------------------------------------------------- */

.hilfe { background: none; border-style: dashed; box-shadow: none; }

/* Bild über den Schritten, ab Tablet daneben. Am Handy nebeneinander wäre das
   Bild zu klein zum Erkennen und der Text zu schmal zum Lesen. */
.hilfe__innen { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 52rem) {
  .hilfe__innen { grid-template-columns: minmax(0, 22rem) 1fr; align-items: start; }
}

.hilfe__bild {
  background: var(--papier-tief);
  border-radius: var(--radius-klein);
  padding: 1rem;
  box-shadow: var(--praegung);
}
.hilfe__svg { display: block; width: 100%; height: auto; color: var(--tinte-leise); }

.hilfe__schritte { margin: 0; }
.hilfe__schritte li { margin-bottom: .55rem; }
.hilfe__schritte li:last-child { margin-bottom: 0; }

/* Bei erzwungenem hohen Kontrast tragen die Zeichnungen nichts bei — dort
   zählt der Text daneben, der ohnehin alles sagt. */
@media (prefers-contrast: more) {
  .hilfe__bild { display: none; }
}

/* ---------------------------------------------------------------------------
   Rücksicht
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  .kachel:hover, .knopf:hover { transform: none; }
}

/* Hoher Kontrast erzwungen: Prägungen und Faser weg, harte Kanten her. */
@media (prefers-contrast: more) {
  :root { --praegung: none; --schatten: none; }
  body::before { display: none; }
  .karte, .gruppe, .kachel, .tabelle-rahmen { border-color: var(--tinte); }
}

@media print {
  body::before, .kopf, .fuss, .leiste, .knopf { display: none; }
  .karte, .gruppe, .kachel { box-shadow: none; border: 1px solid #999; }
}
