/* Das Heft: Papier, Lineatur, Rand, Schrift. Eine Datei fuer alle vier
   Seiten — sonst driften Umschlag und Unterseiten auseinander, und ein
   Besucher, der auf "App laden" klickt, verlaesst das Heft.
   Ausgeliefert flach: die ConfigMap kennt nur Dateinamen. */
/* Selbst gehostet, nicht von Google geladen: die Seite verspricht kein
   Tracking, und ein Font-CDN sieht jede Besucher-IP. Beide Schriften
   stehen unter der SIL OFL. Im Repo liegen sie unter website/fonts/,
   ausgeliefert werden sie flach: die ConfigMap kennt nur Dateinamen. */
@font-face {
  font-family: 'Andika'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('/andika-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Andika'; font-style: normal; font-weight: 700;
  font-display: swap; src: url('/andika-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Atkinson Hyperlegible Next'; font-style: normal;
  font-weight: 400 700; font-display: swap;
  src: url('/atkinson-next.woff2') format('woff2');
}

:root {
  /* DESIGN.md. Rot und Grün fehlen hier mit Absicht: sie sind Zustände
     (Fehler, Erfolg) und keine Markenfarben. */
  --cover-blue: #1f4ba8;
  --cover-blue-deep: #12306e;
  --paper-white: #fbfbfd;
  --paper-label: #ffffff;
  --ink-900: #1f2733;
  --ink-600: #5c6875;
  --ink-on-cover: #ffffff;
  --rule-baseline: #2b59c3;
  --rule-on-cover: #8ad3f2;
  --rule-faint: rgba(199, 205, 214, .37);
  --rand-blue: #4c8fd6;
  --rand-ink: #1c5b84;
  --silbe-blue: #16358a;
  --silbe-sky: #009ec4;

  --pitch: 34px;            /* Lineatur = Zeilenhöhe des Fließtexts */
  --rand-x: clamp(22px, 14vw, 200px);
  --text-x: clamp(46px, 18vw, 260px);
  --measure: 580px;
  --fleiss: clamp(70px, 19vw, 104px);
  --display: clamp(34px, 4.4vw, 52px);
  --body: clamp(16px, 1.5vw, 20px);
}
@media (max-width: 720px) { :root { --pitch: 27px; } }

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper-white);
  color: var(--ink-900);
  font-family: 'Atkinson Hyperlegible Next', system-ui, sans-serif;
  font-size: var(--body);
  line-height: var(--pitch);
}
h1, h2 {
  font-family: Andika, 'Atkinson Hyperlegible Next', system-ui, sans-serif;
  font-weight: 700;
  letter-spacing: -.025em;
  text-wrap: balance;
  margin: 0;
}
a { color: var(--rule-baseline); }

/* ---- Der Bogen: eine Seite des Hefts ------------------------------ */
.blatt {
  position: relative;
  padding: calc(var(--pitch) * 3) 0 calc(var(--pitch) * 3);
  /* Die Lineatur läuft von Rand zu Rand und liegt UNTER allem. Ihr
     Abstand ist die Zeilenhöhe des Fließtexts, damit Text auf der Linie
     sitzt statt von ihr durchgestrichen zu werden. */
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0 calc(var(--pitch) - 1px),
    var(--rule-faint) calc(var(--pitch) - 1px) var(--pitch)
  );
  background-position: 0 calc(var(--pitch) * .78);
}
/* Der Rand. In einem echten Heft korrigiert die Lehrkraft hier — also
   stehen hier die unbequemen Sätze. */
.blatt::before {
  content: '';
  position: absolute; top: 0; bottom: 0; left: var(--rand-x);
  width: 1.5px; background: var(--rand-blue);
}
.satz { margin-left: var(--text-x); max-width: var(--measure); padding-right: 24px; }
/* Text links, Bilder rechts — auf schmalen Schirmen untereinander. */
.spalten-blatt {
  margin-left: var(--text-x); padding-right: 24px;
  display: grid; align-items: start;
  grid-template-columns: minmax(0, var(--measure)) minmax(0, auto);
  gap: clamp(28px, 4vw, 72px);
}
.spalten-blatt > .satz { margin-left: 0; padding-right: 0; max-width: none; }
@media (max-width: 960px) { .spalten-blatt { grid-template-columns: 1fr; } }
.fotos { display: flex; justify-content: flex-start; }
.fotos figure { margin: 0; }
/* Eingeklebt: der Streifen liegt VOR dem Bild und greift über die Kante,
   wie ein Klebestreifen im Heft. */
.foto { position: relative; width: min(286px, 100%); }
.foto img {
  display: block; width: 100%; height: auto; border-radius: 14px;
  box-shadow: 0 12px 26px rgba(0, 0, 0, .16);
}
.foto::before, .foto::after {
  content: ''; position: absolute; left: 50%; z-index: 2;
  width: 104px; height: 26px; background: rgba(214, 196, 158, .78);
}
.foto::before { top: -13px; transform: translateX(-50%) rotate(-2deg); }
.foto::after { bottom: -13px; transform: translateX(-50%) rotate(2deg); }
.fotos--paar .foto:first-child {
  width: min(226px, 100%); margin: 64px -46px 0 0; z-index: 0;
}
.fotos--paar .foto:last-child { z-index: 1; }
@media (max-width: 560px) {
  .fotos--paar .foto:first-child { display: none; }
}
.foto-hinweis { font-size: 14px; color: var(--ink-600); margin: 18px 0 0; }
.satz > * + * { margin-top: var(--pitch); }
.satz h2 + p { margin-top: calc(var(--pitch) * 1.3); }
.satz h2 { font-size: var(--display); line-height: 1.31; }
.satz p { margin: 0; color: var(--ink-600); }
/* `.satz p` schlaegt `.satz > * + *` (spezifischer), also braucht der
   Absatz-Abstand dieselbe Spezifitaet — sonst kleben zwei aufeinander
   folgende Absaetze aneinander. Faellt auf Seiten mit viel Fliesstext auf. */
.satz > * + p { margin-top: var(--pitch); }
/* DER KLASSENNAME STEHT ZWEIMAL DA, und das ist Absicht. `.satz p` weiter
   oben setzt Farbe und margin und ist mit 0-1-1 spezifischer als ein
   einfaches `.randnotiz` (0-1-0) -- die Notiz erbte dadurch schon einmal
   das Grau des Fliesstexts statt des Randblaus, und auf dem Telefon dazu
   margin: 0.
   Davor stand hier `.satz p.randnotiz`. Das behob den Fall, den es damals
   gab, und deckt jede Verschachtelungstiefe INNERHALB von .satz ab. Es
   musste dafuer aber den einen Vorfahren beim Namen nennen -- und schlaegt
   damit nur die eine Regel, die es kennt. Die naechste Regel derselben
   Staerke auf einen anderen Vorfahren (`.blatt p`, `.spalten-blatt p`)
   faengt es nicht ab; der Selektor muesste jedes Mal mitwachsen.
   `.randnotiz.randnotiz` zaehlt 0-2-0 und schlaegt `.satz p` unabhaengig
   davon, wo die Notiz steht und in welcher Reihenfolge die Regeln stehen. */
.randnotiz.randnotiz {
  position: absolute; left: 0; width: calc(var(--rand-x) - 16px);
  text-align: right; margin: 0;
  font-size: 15px; line-height: 22px; color: var(--rand-ink);
}
/* Auf dem Telefon ist der Rand 56 px breit -- dort passt kein Satz hinein.
   Bisher verschwand die Notiz deshalb ganz (display: none), und damit
   fielen acht Saetze weg, die auf jeder Seite das Unbequeme sagen ("Ein
   Kind hat hier kein eigenes Konto."). Gesehen hat die niemand, der die
   Seite auf dem Handy liest, also die meisten.

   Jetzt ruecken sie in den Textfluss und behalten den blauen Strich, nur
   als Kante statt als Rand. Sie stehen damit auch fuer Suchmaschinen da,
   die zuerst die mobile Fassung lesen. */
@media (max-width: 720px) {
  .randnotiz.randnotiz {
    position: static;
    width: auto;
    margin: var(--pitch) 24px var(--pitch) var(--text-x);
    padding-left: 12px;
    text-align: left;
    border-left: 3px solid var(--rand-blue);
  }
  /* Die Regel weiter unten nimmt absolute Notizen aus dem Zeilenabstand
     heraus; im Fluss brauchen sie ihn wieder, siehe margin oben. */
}

/* ---- 01 Umschlag --------------------------------------------------- */
.umschlag {
  position: relative;
  background: var(--cover-blue);
  color: var(--ink-on-cover);
  padding: calc(var(--pitch) * 2) 24px;
  text-align: center;
}
.umschlag::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 0;
  width: clamp(10px, 1.4vw, 20px); background: var(--cover-blue-deep);
}
.schild {
  position: relative;
  max-width: 560px; margin: 0 auto;
  background: var(--paper-label); color: var(--ink-900);
  border-radius: 14px; padding: 46px 40px 34px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .28);
}
/* Zwei Klammern, mit denen das Namensschild aufs Heft geheftet ist. */
.schild::before, .schild::after {
  content: ''; position: absolute; top: 10px; width: 26px; height: 5px;
  border-radius: 2px; background: #b9c0c9;
}
.schild::before { left: 38px; }
.schild::after { right: 38px; }
/* Die Wortmarke IST die Ueberschrift der Seite, nur gezeichnet statt
   gesetzt -- deshalb steht das SVG in einer h1 (Bing bemaengelte die
   fehlende). Die h1-Regel weiter oben gibt letter-spacing: -.025em mit, und
   CSS-Laufweite vererbt sich in SVG-Text hinein: die Silben rueckten
   messbar zusammen (2.448 veraenderte Bildpunkte im Vorher-Nachher). Hier
   zurueckgesetzt, damit die Marke aussieht wie vorher. */
h1.wortmarke { letter-spacing: normal; font-weight: inherit; }
.schild svg { width: min(100%, 320px); height: auto; display: block; margin: 0 auto; }
.felder { margin: 26px 0 0; font-size: 15px; line-height: 30px; color: var(--ink-900); }
.feld { display: flex; gap: 10px; align-items: baseline; }
.feld dt { color: var(--ink-600); flex: 0 0 auto; margin: 0; }
.feld dd {
  margin: 0; flex: 1 1 auto;
  border-bottom: 1px solid var(--rule-faint);
  font-weight: 500; text-align: left;
}
/* Auf dem Heft steht hier der Name. Auf der Seite steht hier ein Wort:
   dieselbe blau angestrichene Zeile, aber sie fragt nach und fuehrt zur
   Silbenseite. KEIN Knopf daneben: ein Formular mit einem einzigen
   Textfeld schickt sich beim Druck auf die Eingabetaste von selbst ab
   (implizites Absenden), und auf dem Telefon heisst diese Taste bei
   type="search" ohnehin schon "Los". Das Eingabefeld TRAEGT die Linie nicht selbst -- sie
   gehoert weiter dem dd, damit die Zeile genauso aussieht wie die beiden
   darueber, ob getippt wurde oder nicht. */
.feld--name dd, .feld--wort dd { border-bottom-color: var(--rand-blue); }
.feld--wort form { display: flex; gap: 8px; align-items: baseline; }
.feld--wort input {
  flex: 1 1 auto; min-width: 0;
  font: inherit; color: inherit;
  background: none; border: 0; padding: 2px 0;
}
/* KEIN KASTEN UM DIE SCHREIBZEILE. Das Feld auf dem Umschlag soll
   aussehen wie die beiden Zeilen darueber -- der Fokusrahmen legte
   stattdessen einen blauen Kasten quer darueber, und beim Tippen stand
   das Wort in einem Formularfeld statt auf einer Linie.

   appearance: none, weil border: 0 nicht reicht: bei type="search"
   zeichnet Safari seinen eigenen runden Rahmen, und WebKit setzt ihn
   ueber die Kante.

   Der Fokus bleibt sichtbar, nur als Linie statt als Rahmen: der
   Schatten legt zwei Pixel unter die vorhandene Kante, zusammen also
   ein dreimal so kraeftiger Strich -- wie fester aufgedrueckt. Als
   box-shadow und nicht als dickerer Rand, weil ein wachsender Rand die
   Zeile um seinen Zuwachs verschieben wuerde. */
.feld--wort input { appearance: none; -webkit-appearance: none; }
.feld--wort input:focus-visible { outline: none; }
.feld--wort dd:focus-within { box-shadow: 0 2px 0 0 var(--rand-blue); }

.cover-lead { max-width: 34rem; margin: calc(var(--pitch)) auto 0; }
.cover-note { font-size: 14px; opacity: .85; margin: calc(var(--pitch) * .6) 0 0; }

/* Fleißbildchen: ein Aufkleber, quer über die Ecke des Schilds. */
/* Das Fleissbildchen klebt ueber der Ecke des Schilds. Es lag bei
   right/top -18/-26px und ragte damit weit aus dem Schild heraus — auf
   schmalen Schirmen ueber den Rand hinaus, weshalb es unter 560px
   kurzerhand ausgeblendet war. Ein Aufkleber, der auf dem Telefon
   verschwindet, ist kein Aufkleber. Jetzt haengt es nur halb ueber der
   Kante und schrumpft mit dem Schirm, statt zu verschwinden. */
.fleiss {
  position: absolute; right: -10px; top: -18px;
  width: var(--fleiss); height: var(--fleiss); border-radius: 50%;
  background: var(--paper-label);
  display: grid; place-items: center; text-align: center;
  box-shadow: 0 5px 12px rgba(0, 0, 0, .3);
  transform: rotate(8deg);
  border: 0; padding: 0; cursor: pointer;
  /* Ueber die Heftklammern: `.schild::after` ist das letzte Kind und malte
     sonst quer ueber seinen Kopf. */
  z-index: 2;
}
/* Der Kopf sitzt IM Aufkleber. Das Nicken beim Klick und der kleine Weg
   zwischen zwei Zellen laufen auf .mk-kopf, nicht auf dem Aufkleber: der
   ist um 8 Grad gedreht, und zwei Transformationen uebereinander wuerden
   ihn aus seiner Stanzung schieben. */
.fleiss .mk-kopf {
  position: absolute; left: 23%; top: 6%;
  width: 54%; height: 54%; inset: auto;
  will-change: transform;
}
/* Er muss INNERHALB der Stanzung bleiben: der gestrichelte Ring sitzt bei
   inset 7px, und ein Kopf, der darueber hinausragt, liest sich als Fehler
   und nicht als Aufkleber. Die Bildunterschrift steht darunter, nicht auf
   seinem Kinn. */
.fleiss b { position: absolute; bottom: 12%; left: 0; right: 0; }
.fleiss b {
  display: block; font-size: calc(var(--fleiss) * .096);
  letter-spacing: .02em; color: var(--rule-baseline); margin-top: 3px;
}
.fleiss::after {
  content: ''; position: absolute; inset: 7px; border-radius: 50%;
  border: 2px dashed var(--silbe-sky);
}
@media (max-width: 560px) {
  .fleiss { right: -4px; top: -12px; }
  .fleiss::after { inset: 5px; border-width: 1.5px; }
}

/* ---- Das Maskottchen ----------------------------------------------- */
/* Derselbe Atlas wie in der App: 25 gerenderte Kopfwinkel, eine Zelle je
   Blickrichtung. Hier folgt er dem Zeiger statt der Geraeteneigung, und er
   sitzt im Fleissbildchen — der Aufkleber traegt laut DESIGN.md den Helden. */
.mk-kopf, .mk-mund {
  position: absolute;
  background-repeat: no-repeat;
  image-rendering: auto;
}
.mk-kopf { inset: 0; background-image: url('/kopf.webp'); }
/* Der Mund ist ein Kind des Kopfes: seine Koordinaten kommen aus der
   Kopfzelle (atlas.json), und so erbt er Verschiebung und Nicken. */
.mk-mund { pointer-events: none; }
.mk-mund { background-image: url('/mund_halb.webp'); }
/* Ein Anstupsen beim Klick — er reagiert auch dann, wenn der Ton noch fehlt. */
.fleiss.spricht .mk-kopf { animation: mk-nicken .5s ease-in-out; }
@keyframes mk-nicken {
  0%, 100% { transform: translateY(0); }
  30% { transform: translateY(3px) scale(1.02); }
}
/* Der Satz, den er spricht, hebt sich waehrenddessen. */
.cover-lead { transition: text-shadow .25s ease; }
.cover-lead.gesprochen { text-shadow: 0 0 18px rgba(138, 211, 242, .55); }
.fleiss:focus-visible {
  outline: 3px solid var(--rule-on-cover); outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) {
  .fleiss { cursor: default; }
  .fleiss.spricht .mk-kopf { animation: none; }
}

/* ---- Knöpfe -------------------------------------------------------- */
.knopf {
  display: inline-block; border-radius: 14px; padding: 18px 40px;
  background: var(--paper-label); color: var(--rule-baseline);
  font: inherit; font-weight: 500; text-decoration: none;
  border: 2px solid var(--rule-baseline); cursor: pointer;
}
/* Auf dem Umschlag liegt unter dem Zettel eine Schreiblinie. Sie ist
   hell, weil eine blaue Linie auf blauem Grund verschwindet. */
.knopf--umschlag { border: 0; margin-top: var(--pitch); }
.knopf-zeile {
  width: 181px; height: 3px; background: var(--rule-on-cover);
  margin: 6px auto 0; border-radius: 2px;
}
.knopf[disabled] {
  border-color: #c7cad6; color: #8d94a1; cursor: not-allowed;
  background: #f3f4f7;
}
/* `display: inline-block` am Knopf schlaegt sonst das UA-`[hidden]`,
   und der Kopier-Knopf stand auch ohne gueltigen Code da. */
[hidden] { display: none !important; }

/* ---- Listen als Hefteinträge --------------------------------------- */
.eintraege { list-style: none; margin: 0; padding: 0; }
.eintraege li {
  display: flex; align-items: baseline; gap: 12px;
  line-height: var(--pitch); font-size: 17px;
}
/* Der Haken ist GEZEICHNET, kein Zeichen. Weder Andika noch Atkinson fuehren
   U+2713 — ein getippter Haken bleibt in diesen Schriften leer, und genau so
   ist er auf der Seite auch nicht erschienen. Blau, nicht gruen: gruen heisst
   in diesem Produkt "richtig gemacht", hier heisst es nur "haben wir". */
.eintraege li::before {
  content: ''; flex: 0 0 auto; align-self: center;
  width: 15px; height: 11px;
  background: var(--rule-baseline);
  clip-path: polygon(13.6% 45%, 0 58%, 38% 100%, 100% 16%, 86% 0, 36% 70%);
}
/* Die Fuehrungslinie zwischen Land und Listenname, wie im Entwurf. */
.eintraege li span:first-of-type { flex: 0 0 auto; }
.eintraege li .fuehrung {
  flex: 1 1 auto; height: 1px; background: var(--rule-faint);
  transform: translateY(-4px);
}
.eintraege li span:last-child {
  color: var(--ink-600); text-align: right; flex: 0 0 auto;
}
/* Schmal wird der Listenname zur Nebensache — der Entwurf zeigt auf dem
   Telefon nur die Laendernamen.
   :not(:first-child) ist der ganze Punkt. Diese Regel ist fuer die
   ZWEITEILIGEN Eintraege gedacht — <span>Land</span><i/><span>Liste</span> —,
   aber .eintraege traegt auch einteilige: die Preisliste ist
   <li><span>Text</span></li>, und dort ist dieselbe span zugleich die erste
   und die letzte. Ohne die Einschraenkung verschwand auf dem Telefon der
   gesamte Text unter "Was es kostet", und stehen blieben zwei Spalten
   nackter Haken. */
@media (max-width: 560px) {
  .eintraege li .fuehrung,
  .eintraege li span:last-child:not(:first-child) { display: none; }
}
.spalten { display: grid; gap: 40px; grid-template-columns: 1fr 1fr; }
@media (max-width: 720px) { .spalten { grid-template-columns: 1fr; } }
.spalte h3 {
  font-family: Andika, sans-serif; font-size: 24px; margin: 0 0 12px;
  font-weight: 700;
}
.liste-breit { margin-left: var(--text-x); max-width: 760px; padding-right: 24px; }

/* Die Woerterliste auf /silben.html. Zweitausend kurze Eintraege in einer
   Spalte waeren eine Papierrolle, also mehrspaltig -- und die Zeilenhoehe
   bleibt die Lineatur, damit die Woerter auf den Linien sitzen statt von
   ihnen durchgestrichen zu werden. */
.silbenliste {
  margin: 0 24px var(--pitch) var(--text-x);
  padding: 0;
  list-style: none;
  columns: 3;
  column-gap: 32px;
  font-size: 17px;
  line-height: var(--pitch);
  color: var(--ink-600);
}
@media (max-width: 900px) { .silbenliste { columns: 2; } }
@media (max-width: 560px) { .silbenliste { columns: 1; } }
.silbenliste li { break-inside: avoid; }
.silbenliste button {
  font: inherit; color: inherit; background: none; border: 0; padding: 0;
  cursor: pointer; text-align: left;
}
.silbenliste button:hover, .silbenliste button:focus-visible {
  color: var(--silbe-blue); text-decoration: underline;
}

/* Der Bogen unter der Silbe, ohne SVG und ohne Messen: eine untere Kante
   mit elliptisch gerundeten Ecken ist genau die Schale, die ein Kind unter
   das Wort malt, und sie passt sich der Silbenbreite von selbst an. Die
   Farben wechseln wie in der App, Rot bleibt den Fehlern. */
.bogen-feld { margin: 0 24px var(--pitch) var(--text-x); min-height: 96px; }
.bogen-wort {
  display: flex; flex-wrap: wrap; gap: 10px;
  font-family: Andika, 'Atkinson Hyperlegible Next', sans-serif;
  font-weight: 700; font-size: clamp(30px, 6vw, 52px); line-height: 1.1;
}
.bogen-wort span {
  padding: 0 4px 12px;
  border-bottom: 5px solid currentColor;
  border-radius: 0 0 46% 46% / 0 0 26px 26px;
}
.bogen-wort span:nth-child(odd) { color: var(--silbe-blue); }
.bogen-wort span:nth-child(even) { color: var(--silbe-sky); }
.bogen-wort + p { margin-top: 10px; }
#suche {
  font: inherit; padding: 6px 10px;
  border: 1.5px solid var(--rand-blue); border-radius: 8px;
  background: var(--paper-white); color: inherit; min-width: 12em;
}

/* ---- Schreiblineatur ----------------------------------------------- */
.lineatur {
  background: var(--paper-label); border-radius: 14px;
  border: 1px solid rgba(199, 205, 214, .8);
  padding: 26px 30px; max-width: 520px;
}
.lineatur svg { width: 100%; height: auto; display: block; }

.preis { font-family: Andika, sans-serif; font-weight: 700; font-size: 44px; line-height: 1.2; }
.klein { font-size: 15px; line-height: 24px; color: var(--ink-600); }

/* ---- 08 Rückseite -------------------------------------------------- */
.rueckseite {
  position: relative; background: var(--cover-blue);
  color: var(--ink-on-cover);
  padding: calc(var(--pitch) * 2) 24px calc(var(--pitch) * 2)
           max(40px, var(--text-x));
}
.rueckseite::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 0;
  width: clamp(10px, 1.4vw, 20px); background: var(--cover-blue-deep);
}
.rueckseite a { color: var(--ink-on-cover); }
.spalten--fuss { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 760px; }
@media (max-width: 560px) { .spalten--fuss { grid-template-columns: 1fr; gap: 20px; } }
.spalten--fuss h4 { margin: 0 0 8px; font-size: 15px; }
.spalten--fuss ul { list-style: none; margin: 0; padding: 0; font-size: 15px; }
/* Die Schlusszeile und der Weg zurueck nach oben teilen sich eine Zeile:
   der Satz links, der Anker rechts, und auf schmalen Schirmen untereinander.
   Die Trennlinie gehoert jetzt dem Kasten, nicht mehr dem Absatz -- sonst
   liefe sie nur ueber die Haelfte. */
.fuss-abschluss {
  display: flex; flex-wrap: wrap; justify-content: space-between;
  align-items: baseline; gap: 10px 32px;
  margin: calc(var(--pitch) * 2) 0 0; padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, .25);
  max-width: 760px;
}
.fuss-schluss { margin: 0; font-size: 14px; }
/* NACH OBEN, und zwar als gewoehnlicher Anker am Ende der Seite statt als
   schwebender Knopf. Die Seite ist ein Heft: ein Knopf, der ueber dem Text
   mitfaehrt, deckt auf dem Telefon genau die Spalte zu, die man liest. Ein
   Anker steht da, wo man ihn sucht -- unten -- und braucht kein JavaScript,
   keinen Scroll-Horcher und keine Ausnahme fuer prefers-reduced-motion.
   Der Pfeil ist gezeichnet wie der in .zurueck: U+2191 fehlt in beiden
   Schriften der Seite. */
.nach-oben { margin: 0; font-size: 14px; }
.nach-oben a { display: inline-flex; align-items: center; gap: 8px; }
.nach-oben svg { width: 12px; height: 17px; flex: 0 0 auto; }
/* Auf den Unterseiten steht er unter dem letzten Absatz statt im Fuss --
   silben.html hat gar keinen. Dort traegt er den Einzug des Fliesstexts. */
.blatt--seite > .nach-oben { margin-left: var(--text-x); font-size: 16px; }
:focus-visible { outline: 3px solid var(--rule-on-cover); outline-offset: 3px; }

/* ---- Unterseiten ----------------------------------------------------- */
/* Der Weg zurueck steht dort, wo im Heft die Seitenzahl stuende. */
.zurueck {
  margin: 0 0 0 var(--text-x); padding-right: 24px;
  font-size: 16px;
}
/* Der Pfeil ist gezeichnet: U+2190 fehlt in BEIDEN Schriften der Seite, ein
   getipptes ← faellt also auf irgendeine Systemschrift zurueck — oder auf
   gar keine. */
.zurueck a { display: inline-flex; align-items: center; gap: 8px; }
.zurueck svg { width: 17px; height: 12px; flex: 0 0 auto; }
/* Eine Unterseite ist EIN Blatt: die Lineatur faengt nur einmal an. Mehrere
   .blatt untereinander wuerden das Linienraster an jeder Kante neu setzen —
   und zwei Linien stuenden dort ungleich weit auseinander. */
.blatt--seite > * + *:not(.randnotiz) { margin-top: var(--pitch); }
.blatt--seite > h2 { margin-left: var(--text-x); }
.satz h1 { font-size: var(--display); line-height: 1.31; }
.satz h1 + p { margin-top: calc(var(--pitch) * 1.3); }
/* Auf einer Unterseite traegt h1 den Titel, h2 die Abschnitte — eine Stufe
   kleiner als auf dem Umschlag, sonst schreit jeder Zwischentitel. */
.blatt--seite .satz h2 { font-size: 25px; line-height: 34px; letter-spacing: -.02em; }
.blatt--seite .satz h2 + p,
.blatt--seite .satz h2 + ol,
.blatt--seite .satz h2 + .begriffe,
.blatt--seite .satz h2 + address { margin-top: 12px; }
.satz--breit { max-width: 720px; }
.anschrift { font-style: normal; color: var(--ink-900); font-weight: 500; }

/* Nummerierte Schritte: die Ziffer steht im Bogen-Blau wie in der App. */
.schritte { list-style: none; margin: 0; padding: 0; counter-reset: schritt; }
/* `.schritte`/`.begriffe` setzen margin: 0 und schlagen damit den
   Geschwister-Abstand — ohne das hier klebt die Liste am Absatz davor. */
.satz > * + .schritte, .satz > * + .begriffe { margin-top: var(--pitch); }
.schritte li {
  counter-increment: schritt;
  display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 14px;
  color: var(--ink-600);
}
.schritte li + li { margin-top: 10px; }
.schritte li::before {
  content: counter(schritt);
  font-family: Andika, sans-serif; font-weight: 700; font-size: 21px;
  color: var(--rule-baseline);
}
.satz .schritte li > * { margin: 0; }

/* Begriff und Erklaerung, durch eine Haarlinie getrennt wie im Hefteintrag. */
.begriffe { margin: 0; border-top: 1px solid var(--rule-faint); }
.begriffe > div {
  display: grid; grid-template-columns: 168px minmax(0, 1fr); gap: 24px;
  padding: 12px 0 14px; border-bottom: 1px solid var(--rule-faint);
}
.begriffe dt { margin: 0; font-weight: 500; line-height: 26px; }
.begriffe dd { margin: 0; color: var(--ink-600); font-size: 17px; line-height: 28px; }
@media (max-width: 560px) {
  .begriffe > div { grid-template-columns: 1fr; gap: 2px; }
}

/* Die Bauten-Liste. Keine Karte, keine Streifen: Zeilen auf Linien. */
.tabelle-rolle { margin-left: var(--text-x); padding-right: 24px;
  max-width: 880px; overflow-x: auto; }
table.bauten { border-collapse: collapse; width: 100%; min-width: 640px;
  font-size: 16px; line-height: 22px; }
table.bauten th, table.bauten td {
  text-align: left; padding: 11px 20px 11px 0; white-space: nowrap;
  border-bottom: 1px solid var(--rule-faint);
}
table.bauten thead th {
  font-weight: 500; font-size: 12.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-600); padding-bottom: 8px;
}
table.bauten tbody td { color: var(--ink-600); }
table.bauten tbody td:first-child { color: var(--ink-900); }
.variante { text-transform: uppercase; font-size: 12.5px; letter-spacing: .06em; }
.variante--release { color: var(--rule-baseline); }
.pruefsumme {
  font-family: ui-monospace, 'Cascadia Mono', Consolas, monospace;
  font-size: 14px; cursor: pointer;
  border-bottom: 1px dashed var(--rule-faint); background: none; border-width: 0 0 1px;
  padding: 0; color: inherit;
}
.pruefsumme:hover { color: var(--ink-900); border-bottom-color: var(--rule-baseline); }
.laden { color: var(--rule-baseline); font-weight: 500; }

/* Das Kaertchen mit dem Code — als waere es ins Heft gelegt worden. */
.kaertchen {
  margin-left: var(--text-x); max-width: var(--measure);
  background: var(--paper-label); border: 1px solid rgba(199, 205, 214, .8);
  border-radius: 4px; box-shadow: 0 2px 10px rgba(31, 39, 51, .1);
  padding: 26px 36px 28px; text-align: center;
}
.kaertchen .marke {
  margin: 0; font-size: 14px; line-height: 22px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-600);
}
.kaertchen .code {
  font-family: Andika, sans-serif; font-weight: 700;
  font-size: 40px; line-height: 54px; letter-spacing: .26em;
  color: var(--rule-baseline); margin: 8px 0 0; overflow-wrap: anywhere;
}
/* Ein Link ohne gueltigen Code ist keine Ueberschrift, sondern ein Hinweis. */
.kaertchen .code--ungueltig {
  font-family: inherit; font-weight: 400; font-size: 17px; line-height: 26px;
  letter-spacing: 0; color: var(--ink-600);
}
.kaertchen .knopf { padding: 9px 20px; border-radius: 3px; border-width: 1.5px;
  margin-top: 8px; font-size: 16px; }

code {
  font-family: ui-monospace, Consolas, "Courier New", monospace;
  font-size: .86em; background: rgba(199, 205, 214, .28);
  border-radius: 3px; padding: .1em .35em;
}
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
