/* ------------------------------------------------------------------
   Die Lernseite. Dieser Block stammt woertlich aus dem abgenommenen
   Prototyp docs/design/prototyp.html (dort der <style>-Block, Zeilen
   4 bis 445); beim Umzug wurde nur die Einrueckung um zwei Zeichen
   zurueckgenommen und dieser Kopfkommentar angepasst. Farbwerte,
   Winkel, Schatten und die Dauer der Umklapp-Animation stammen
   woertlich aus der freigegebenen Spec
   (docs/superpowers/specs/2026-08-27-flashcards-design.md, Abschnitt 6).
   Schrift bewusst system-ui: die echte Seite soll keine Webfont-
   Abhaengigkeit haben.

   Ergaenzt wurden nur die beiden Bloecke ganz am Ende: "Gerendertes
   Markdown" - den brauchte der Prototyp nicht, weil er alle Inhalte als
   Klartext gesetzt hat, die echte Seite bekommt an vier Stellen
   Block-HTML aus app/markdown.rendern() - und "Lange Inhalte", der eine
   Hoehengrenze fuer den Zettel zieht. Kein bestehender Wert wurde
   angefasst: keine Farbe, kein Winkel, keine Zeit, keine Groesse.
   ------------------------------------------------------------------ */

:root {
  --tafel-oben:   #2a3138;
  --tafel-unten:  #16191d;
  --raster:       rgba(255, 255, 255, .028);

  --zettel-vorn:  linear-gradient(158deg, #ffe57a 0%, #ffd23f 100%);
  --zettel-hinten: linear-gradient(158deg, #ffdf6b 0%, #f7c62f 100%);
  --zettel-stapel-1: #e9bf3a;
  --zettel-stapel-2: #f0cd52;
  --tinte:        #2b2410;

  --richtig:      #2f9e52;
  --richtig-rand: #257e41;
  --falsch:       #d1392f;
  --falsch-rand:  #a72d25;

  --spur:         #2c343c;
  --fuellung:     #ffd23f;
  --gedaempft:    #7b8996;
  --gedaempft-hell: #aebac6;

  --schatten:     0 18px 32px rgba(0, 0, 0, .55);
  --umklappen:    .55s cubic-bezier(.2, .7, .3, 1);

  --schrift: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100dvh;
  background:
    radial-gradient(120% 90% at 50% 0%, var(--tafel-oben) 0%, var(--tafel-unten) 70%),
    var(--tafel-unten);
  color: var(--gedaempft-hell);
  font-family: var(--schrift);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Das feine Raster der Tafel. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(var(--raster) 1px, transparent 1px),
    linear-gradient(90deg, var(--raster) 1px, transparent 1px);
  background-size: 22px 22px;
}

.buehne {
  position: relative;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  max-width: 46rem;
  margin: 0 auto;
  padding: 0 1rem;
}

/* ===================== Kopfzeile ===================== */

.kopf {
  flex: none;
  padding: 1rem .25rem .75rem;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.kopf[hidden] { display: none; }

.kopf-zeile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: .8rem;
  color: var(--gedaempft);
  font-variant-numeric: tabular-nums;
}

.balken {
  height: 3px;
  background: var(--spur);
  border-radius: 2px;
  overflow: hidden;
}
.balken span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--fuellung);
  transition: width .3s ease;
}

.beenden {
  background: none;
  border: none;
  color: var(--gedaempft);
  font: inherit;
  font-size: .8rem;
  cursor: pointer;
  padding: .25rem .4rem;
  border-radius: 6px;
}
@media (hover: hover) { .beenden:hover { color: var(--gedaempft-hell); } }

/* ===================== Buehnenmitte ===================== */

.mitte {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem 0;
  min-height: 0;
}

/* ===================== Der Zettel ===================== */

.stapel {
  position: relative;
  width: 100%;
  max-width: 34rem;
}

.geist {
  position: absolute;
  inset: 0;
  border-radius: 3px 3px 6px 6px;
  box-shadow: 0 10px 20px rgba(0, 0, 0, .45);
}
.geist-1 { background: var(--zettel-stapel-1); transform: rotate(-2.2deg) translate(-7px, 7px); }
.geist-2 { background: var(--zettel-stapel-2); transform: rotate(1.2deg) translate(4px, 3px); }
.geist[hidden] { display: none; }

.karte {
  position: relative;
  perspective: 1400px;
}
/* Nur Ankerpunkt fuer die Tabulatorreihenfolge, kein sichtbarer Ring. */
.karte:focus { outline: none; }

/* Raster statt absoluter Positionierung, und das ist der Kern der Sache.

   Vorher lag die Rueckseite mit "position: absolute; inset: 0" auf der
   Vorderseite und uebernahm damit deren Hoehe. Bei kurzer Frage und langer
   Antwort - dem Normalfall - bekam der lange Text die Hoehe des kurzen, und
   die max-height weiter unten kam auf der Rueckseite nie zum Zuge.
   Nachgemessen am Handy (390x844): Rueckseite 272 px hoch, Inhalt 839 px,
   erlaubt waeren 612 px gewesen; die Knoepfe am unteren Kartenrand waren
   dabei abgeschnitten.

   Jetzt liegen beide Seiten in derselben Rasterzelle (grid-area: 1 / 1) und
   ueberlagern sich wie zuvor - aber jede bekommt ihre eigene, vom Inhalt
   bestimmte Hoehe. "align-items: start" ist dafuer Pflicht: Ohne das
   streckt das Raster beide Seiten auf die Hoehe der hoeheren, und die
   Messung im Runner (hoeheNachfuehren) bekaeme fuer beide denselben Wert.

   Die Hoehe des Rahmens setzt der Runner auf die der gerade sichtbaren
   Seite; "height" gehoert deshalb mit in den Uebergang, damit die Karte
   beim Umdrehen weich waechst statt zu springen. */
.karte-innen {
  position: relative;
  display: grid;
  align-items: start;
  transition: transform var(--umklappen), height var(--umklappen);
  transform-style: preserve-3d;
}
.karte.gedreht .karte-innen { transform: rotateY(180deg); }
.karte.ohne-animation .karte-innen { transition: none; }

.seite {
  /* Beide Seiten in dieselbe Rasterzelle: Sie ueberlagern sich, ohne dass
     eine von ihnen aus dem Fluss genommen werden muss. Siehe .karte-innen. */
  grid-area: 1 / 1;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 3px 3px 6px 6px;
  background: var(--zettel-vorn);
  color: var(--tinte);
  box-shadow: var(--schatten);
  padding: 1.5rem 1.4rem 1.3rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  min-height: 20rem;
}
.seite.rueckseite {
  transform: rotateY(180deg);
  background: var(--zettel-hinten);
}

.augenbraue {
  font-size: .65rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  opacity: .5;
  font-weight: 600;
}

.frage {
  font-size: 1.25rem;
  line-height: 1.35;
  font-weight: 650;
  text-wrap: balance;
  margin: 0;
}
.frage :is(ul, ol) { margin: .5rem 0 0; padding-left: 1.2rem; font-weight: 500; font-size: 1.05rem; }
.frage li + li { margin-top: .2rem; }

.hinweis {
  margin-top: auto;
  font-size: .7rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  opacity: .45;
}

/* --------- Antworten --------- */

.antworten {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

.antwort {
  display: flex;
  align-items: center;
  gap: .65rem;
  width: 100%;
  min-height: 2.75rem;
  padding: .6rem .75rem;
  border: 1.5px solid transparent;
  border-radius: 8px;
  background: rgba(255, 255, 255, .42);
  color: inherit;
  font: inherit;
  font-size: .95rem;
  text-align: left;
  cursor: pointer;
  transition: background .15s ease, transform .1s ease;
}
/* Nur fuer Geraete mit echtem Mauszeiger. Auf einem Touchgeraet bleibt
   der Hover-Zustand am zuletzt beruehrten Element haengen, bis anderswo
   getippt wird. Beim Kartenwechsel wird die Antwortliste neu gebaut, und
   der Knopf, der an die zuletzt beruehrte Stelle rutscht, erbt ihn: Auf
   einer noch unbeantworteten Frage stand dann eine Antwort heller da als
   die uebrigen und sah aus wie ein Hinweis auf die Loesung - und traf,
   weil das Mischen zufaellig ist, genauso oft die falsche.
   Festgehalten in tests/browser/test_hover_am_handy.py. */
@media (hover: hover) {
  .antwort:hover:not(:disabled) { background: rgba(255, 255, 255, .72); }
}
.antwort:active:not(:disabled) { transform: translateY(1px); }
.antwort:disabled { cursor: default; }
.antwort:focus-visible { outline: 3px solid var(--tinte); outline-offset: 2px; }

.taste {
  flex: none;
  width: 1.4rem;
  height: 1.4rem;
  display: grid;
  place-items: center;
  border-radius: 5px;
  background: rgba(43, 36, 16, .14);
  font-size: .7rem;
  font-weight: 700;
}

/* --------- Rueckseite: Aufloesung --------- */

.rueckseite { align-items: center; justify-content: center; text-align: center; }

.urteil { font-size: 1.65rem; font-weight: 800; margin: 0; }
.urteil.ja { color: #1d7a3c; }
.urteil.nein { color: #b3271e; }

.loesung { font-size: 1.05rem; line-height: 1.45; margin: 0; }
.loesung .deine { opacity: .65; }
.loesung strong { font-size: 1.15rem; }

.erklaerung {
  font-size: .85rem;
  line-height: 1.5;
  opacity: .72;
  max-width: 26rem;
  margin: 0;
}

/* --------- Knoepfe auf dem Zettel --------- */

.knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  border: none;
  border-radius: 8px;
  padding: .7rem 1.1rem;
  font: inherit;
  font-size: .9rem;
  font-weight: 600;
  cursor: pointer;
  background: var(--tinte);
  color: #ffd23f;
  transition: transform .1s ease, opacity .15s ease;
}
/* Tastenkuerzel auf dunklem Knopf braucht eine hellere Plakette als auf dem Zettel. */
.knopf .taste { background: rgba(255, 255, 255, .2); color: inherit; }
.knopf.leise .taste { background: rgba(43, 36, 16, .16); }
@media (hover: hover) { .knopf:hover { opacity: .88; } }
.knopf:active { transform: translateY(1px); }
.knopf:focus-visible { outline: 3px solid var(--tinte); outline-offset: 3px; }
.knopf.leise { background: rgba(43, 36, 16, .12); color: var(--tinte); }

.selbsteinschaetzung { display: flex; gap: .5rem; flex-wrap: wrap; justify-content: center; }

/* ===================== Fusszeile ===================== */

.fuss {
  flex: none;
  padding: .75rem .25rem 1.25rem;
  display: flex;
  gap: .6rem;
}
.fuss[hidden] { display: none; }

.navi {
  flex: 1;
  min-height: 3rem;
  border: none;
  border-radius: 10px;
  background: #262f38;
  color: #c6d0da;
  font: inherit;
  font-size: .95rem;
  cursor: pointer;
  transition: background .15s ease;
}
@media (hover: hover) { .navi:hover:not(:disabled) { background: #303b46; } }
.navi:disabled { opacity: .35; cursor: default; }
.navi:focus-visible { outline: 3px solid var(--fuellung); outline-offset: 2px; }

.tastenleiste {
  display: none;
  text-align: center;
  font-size: .72rem;
  color: #6f7c89;
  padding-bottom: 1.25rem;
  letter-spacing: .02em;
}

/* Zeigegeraet mit Hover, also Rechner: Tastenleiste statt Balken. */
@media (hover: hover) and (pointer: fine) {
  .fuss { display: none; }
  .tastenleiste { display: block; }
}

/* ===================== Startseite ===================== */

.klasse {
  align-self: flex-start;
  font-size: .68rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: 700;
  background: rgba(43, 36, 16, .16);
  padding: .3rem .7rem;
  border-radius: 20px;
}

.titel { font-size: 1.7rem; line-height: 1.15; font-weight: 800; margin: 0; text-wrap: balance; }
.beschreibung { font-size: .95rem; line-height: 1.5; opacity: .78; margin: 0; }

.zusammensetzung {
  display: flex;
  gap: 1.5rem;
  font-size: .78rem;
  opacity: .7;
  font-variant-numeric: tabular-nums;
}
.zusammensetzung b { display: block; font-size: 1.3rem; opacity: 1; }

/* ===================== Ergebnis ===================== */

.punktzahl { font-size: 3.4rem; font-weight: 850; line-height: 1; margin: 0; font-variant-numeric: tabular-nums; }
.punktzahl small { font-size: 1.15rem; font-weight: 650; opacity: .5; }

.fazit { font-size: 1.05rem; font-weight: 650; margin: 0; }

.aufschluesselung { display: flex; gap: .6rem; width: 100%; }
.kachel {
  flex: 1;
  background: rgba(255, 255, 255, .42);
  border-radius: 9px;
  padding: .6rem .7rem;
  font-size: .72rem;
  text-align: left;
  font-variant-numeric: tabular-nums;
}
.kachel b { display: block; font-size: 1.2rem; }
.kachel.gut b { color: #1d7a3c; }
.kachel.schlecht b { color: #b3271e; }

.fehlerliste {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: .4rem;
  max-height: 11rem;
  overflow-y: auto;
  text-align: left;
}
.fehler {
  background: rgba(255, 255, 255, .42);
  border-left: 3px solid var(--falsch);
  border-radius: 5px;
  padding: .45rem .6rem;
  font-size: .78rem;
  line-height: 1.4;
}
.fehler i { font-style: normal; opacity: .6; }
.fehler b { color: #1d7a3c; }

.ergebnis-knoepfe { display: flex; gap: .5rem; width: 100%; flex-wrap: wrap; }
.ergebnis-knoepfe .knopf { flex: 1; min-width: 9rem; }

/* ===================== Kleine Schirme ===================== */

@media (max-width: 30rem) {
  .buehne { padding: 0 .75rem; }
  .seite { padding: 1.2rem 1.1rem 1.1rem; min-height: 17rem; }
  .frage { font-size: 1.12rem; }
  .titel { font-size: 1.45rem; }
  .punktzahl { font-size: 2.9rem; }
}

@media (prefers-reduced-motion: reduce) {
  .karte-innen, .balken span, .antwort, .knopf, .navi { transition: none !important; }
}

.nur-fuer-screenreader {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.fussnote {
  flex: none;
  text-align: center;
  font-size: .7rem;
  color: #55616c;
  padding: 0 0 1rem;
  line-height: 1.5;
}

/* ===================== Gerendertes Markdown ===================== */

/* Der einzige Block, der im Prototyp nicht steht. Der Prototyp setzte
   alle Inhalte als Klartext; die echte Seite setzt vier Felder als HTML
   ein (vorderseite, rueckseite, erklaerung, beschreibung - alle aus
   app/markdown.rendern()). Das ist Block-Markup: schon "Sechs Monate"
   wird dort zu <p>Sechs Monate</p>. Ohne die folgenden Regeln braechte
   der Absatzabstand des ersten und letzten Kindes die Karte aus dem
   Raster. Jeder Knoten, der solches HTML traegt, bekommt im Runner
   zusaetzlich die Klasse .markdown - dieselbe Klasse ist damit auch der
   Suchbegriff, mit dem sich alle innerHTML-Stellen finden lassen. */

.markdown > :first-child { margin-top: 0; }
.markdown > :last-child { margin-bottom: 0; }

/* In der Fehlerliste steht die Vorderseite in derselben Zeile wie die
   Loesung, getrennt nur durch <br>. Ein Absatz erzeugte dort eine
   zusaetzliche Leerzeile - im Prototyp gab es keinen, weil dort ein
   reiner Textknoten stand. */
/* Die Aufzaehlung deckt alle Blocktags ab, die app/markdown.py
   durchlaesst (ERLAUBTE_TAGS): p, ul, ol, li, pre, blockquote, h3, h4.
   Mit nur p, ul, ol, li blieben pre, blockquote, h3 und h4 Bloecke und
   erzeugten genau die Leerzeile, die diese Regel verhindern soll. */
.fehler .markdown :is(p, ul, ol, li, pre, blockquote, h3, h4) { display: inline; margin: 0; padding: 0; }

/* Ein sehr langes Wort oder ein Codeblock aus dem Markdown darf die
   Karte nicht auseinanderziehen; die Seite scrollt laut Spec nie
   waagerecht. */
.seite { overflow-wrap: break-word; }
.seite pre { overflow-x: auto; }

/* ===================== Lange Inhalte ===================== */

/* Der zweite Block, der im Prototyp nicht steht - und die einzige
   Stelle, an der Prototyp-CSS ueberhaupt eine Wirkung aendert.

   .seite kannte weder eine Hoehengrenze noch einen Ueberlauf. Die
   Rueckseite liegt absolut auf der Vorderseite (position: absolute;
   inset: 0) und uebernimmt deren Hoehe. Solange die Rueckseite kuerzer
   ist als die Vorderseite - wie in allen sechs Prototyp-Karten - faellt
   das nicht auf. Mit echten Daten (Rueckseite plus Erklaerung, bis 5000
   Zeichen je Feld) lief der Inhalt sichtbar ueber Fusszeile und
   Tastenleiste hinaus, ohne zu scrollen; nachgemessen waren es 604 px
   unter dem Zettelrand. Die Spec verlangt: "Lange Fragen scrollen
   innerhalb der Karte."

   Die Grenze: 100dvh minus dem, was ausserhalb der Karte steht.
   Nachgemessen sind das 12,32rem am Handy (Kopfzeile, die beiden
   Navigationsbalken, die Fussnote) und 12,81rem am Rechner (Kopfzeile,
   Tastenleiste, Fussnote). 14,5rem deckt beide mit Luft ab.

   Kurze Karten aendern sich dadurch nicht: min-height (20rem, am
   kleinen Schirm 17rem) gewinnt in CSS gegen max-height, und wer die
   Grenze nicht erreicht, sieht keine Scrollleiste - overflow-y: auto
   zeigt sie nur, wenn wirklich etwas ueberlaeuft. Eine Scrollleiste bei
   einer Zweizeilen-Antwort waere schlimmer als der Fehler.

   overflow-x steht ausdruecklich dabei, weil es sonst stillschweigend
   passiert: Steht eine Achse auf visible und die andere nicht, rechnet
   CSS die erste auf auto hoch. Sichtbare Folge, hier nachgemessen an
   Karte 1 von feste-tafel-prueft: Ein unteilbar langes Wort
   ("Donaudampfschifffahrts...") ragte bisher ueber den Zettelrand auf
   den dunklen Hintergrund hinaus; jetzt endet es am Rand und die 30 px
   sind innerhalb der Karte erreichbar. Die Seite selbst scrollt
   weiterhin nie waagerecht - das bleibt Zusage der Spec. */
.seite {
  max-height: calc(100dvh - 14.5rem);
  overflow-y: auto;
  overflow-x: auto;
}

/* Dazu gehoert zwingend das "safe". Die Rueckseite zentriert ihren
   Inhalt (justify-content und align-items: center, beides aus dem
   Prototyp). Zentrierter Flex-Inhalt, der laenger ist als sein Kasten,
   ragt nach BEIDEN Seiten hinaus - und was vor dem Anfang des
   Scrollbereichs liegt, ist mit keiner Geste mehr erreichbar.
   Nachgemessen: Die Ueberschrift "Antwort" stand bei scrollTop = 0
   336 px ueber dem oberen Zettelrand, also unwiederbringlich fort. Erst
   mit dem Ueberlauf oben faellt das auf; vorher lief der Inhalt einfach
   sichtbar aus der Karte heraus.

   "safe" schaltet die Zentrierung genau dann auf den Anfang um, wenn
   der Inhalt ueberlaeuft. Passt er - also bei jeder kurzen Karte -, ist
   es unveraendert center, Pixel fuer Pixel. */
.seite.rueckseite {
  justify-content: safe center;
  align-items: safe center;
}

/* ===================== Seiten mit einem Satz ===================== */

/* Der dritte Block, den der Prototyp nicht kennt. Startseite und
   Fehlerseiten benutzen denselben Zettel wie die Lernseite, tragen
   darauf aber einen Satz statt einer ganzen Karte.

   Der Zettel ist auf Kartenlaenge ausgelegt: min-height 20rem, am
   kleinen Schirm 17rem. Mit zwei Zeilen Text darin bleibt der groesste
   Teil leer und der Satz klebt oben - eine Flaeche, die aussieht, als
   fehle etwas. Deshalb hier, und nur hinter der Klasse "knapp":

   min-height 0 laesst den Zettel auf seinen Inhalt schrumpfen; die
   Polsterung von .seite (1,5rem oben, 1,3rem unten) gibt ihm den Rand,
   den ein Zettel braucht. justify-content und align-items setzen den
   Satz in die Mitte statt an den oberen Rand - dieselben beiden Zeilen
   mit "safe", die schon .seite.rueckseite benutzt, und aus demselben
   Grund: Ein ungewoehnlich langer Text darf nicht nach oben aus dem
   Scrollbereich herauslaufen.

   Keine neue Farbe, kein neuer Winkel, keine neue Zeit: Verlauf,
   Schatten, Radius, Tinte und Breite bleiben die des Zettels. */
.buehne.knapp .seite {
  min-height: 0;
  justify-content: safe center;
  align-items: safe center;
  text-align: center;
}
