/* Die Simulation: ein Telefon, das sich beim Scrollen zum Leser dreht, und
   darin GingR, wie es wirklich aussieht: erst Home, dann das laufende Workout,
   in dem ein Satz eingetragen wird, zuletzt die Analyse.

   Drei Regeln, an denen der Eindruck hängt:
   1. Den Fortschritt schreibt sim.js als eine Zahl --p (0 bis 1) an die Section.
      Drehung, Balken, Goldlicht und das Rollen im Telefon rechnet CSS daraus;
      die Schritte sind Klassen an der Figur um die Telefone (.sim-stand).
      Zurückscrollen spult deshalb wirklich zurück.
   2. Bewegt wird nur über transform und opacity. Zustände wechseln hart per
      Klasse, ohne Farbübergänge — so macht es auch die App (Keypad, Pausenkarte
      und ein anderer Tab erscheinen dort ohne Animation). Eine Zugabe dieser
      Seite ist das Aufleben auf Home und Analyse (siehe dort): in der App
      stehen diese beiden Tabs still.
   3. Im Telefon zählt der Maßstab der App. Der Bildschirm ist ein Container,
      --app-pt ist ein iOS-Punkt bei 402 pt Breite; jedes Maß unten ist ein
      pt-Wert aus GymApp (src/theme/tokens.ts und die Komponenten der drei
      Screens, gegengemessen an den Store-Bildern 01-workout.png, 02-home.png
      und 04-analyse.png in assets/store/screenshots-de-2026-10/, 3,28 px je
      pt). So stimmt das Verhältnis bei jeder Telefongröße.

   Stand: das Neudesign der App vom 04.10.2026.

   Farben: nur die Dunkel-Tokens der App (tokens.ts palette.dark) plus die am
   Store-Bild gemessenen iOS-Werte für Glasknöpfe und Kopflinie. Auf dem Grund
   #131311 (gerechnet, WCAG): Text #F2F0EB 16,3:1 · Grau #A29D92 6,9:1 · Orange #F0942E 8,0:1. */

/* ================================================================ Seitenteil */

.sim {
  --sim-grund: #131311;
  --sim-text: #F2F0EB;
  --sim-grau: #A29D92;
  --sim-akzent: #F0942E;
  --sim-linie: #33302A;

  /* Fortschritt 0 bis 1. Ohne Skript bleibt 1 stehen, also der Endzustand. */
  --p: 1;
  /* Anfahrt 0 bis 1: wie weit die Bühne schon hereingekommen ist (nur GingR). */
  --a: 1;

  position: relative;
  background: var(--sim-grund);
  color: var(--sim-text);
  /* Dieselbe linke Kante wie alle Kapitel (styles.css --pad). */
  padding-inline: var(--pad, clamp(20px, 5vw, 64px));
}

/* Die Strecke, über die gescrollt wird. In vh, weil sich der Weg am Bildschirm
   bemessen soll, nicht am Text. Die Seite hat eine harte Höhengrenze. */
.sim-strecke { height: 200vh; position: relative; }
@media (max-width: 760px) { .sim-strecke { height: 225vh; } }

.sim-buehne {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(260px, 30vw, 390px);
  /* Eine Zeile über die volle Bühnenhöhe: das Telefon misst sich an ihr. */
  grid-template-rows: minmax(0, 1fr);
  align-items: center;
  gap: clamp(28px, 5vw, 80px);
  max-width: var(--max, 1180px);
  margin-inline: auto;
  padding-block: clamp(16px, 4vh, 40px);
}
@media (max-width: 860px) {
  .sim-buehne {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    align-items: start;
    gap: 16px;
    padding-block: 16px;
  }
}

/* ---------------------------------------------------------------- Beschriftung */
.sim-text { align-self: center; min-width: 0; }
/* Die Überschrift steht seit dem 26.09. als Kapitelkopf vor der Bühne
   (styles.css „Kapitelköpfe“); in der Textspalte beginnt es mit dem Vorsatz. */
.sim-vorsatz {
  margin: 0;
  max-width: 30em;
  color: var(--sim-grau);
  font-size: clamp(1rem, 1.4vw, 1.125rem);
}

/* Die Takte liegen im selben Rasterfeld übereinander; sichtbar ist der, der dran
   ist. Das Feld ist so hoch wie der längste Takt, deshalb springt nichts, und
   es braucht keine geschätzte Mindesthöhe, die an einer Sprache reißt. */
.sim-takte {
  display: grid;
  margin: clamp(18px, 3vh, 32px) 0 0;
  padding: 0;
  list-style: none;
}
.sim-takte li {
  grid-area: 1 / 1;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition: opacity 260ms ease, transform 260ms ease;
  font-size: clamp(1.0625rem, 1.8vw, 1.375rem);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.3;
}
.sim-takte li.ist-da { opacity: 1; transform: none; }
.sim-nr {
  flex: none;
  width: 1.75rem;
  color: var(--sim-akzent);
  font-variant-numeric: tabular-nums;
  font-size: 0.8125rem;
  font-weight: 600;
  padding-top: 0.35em;
}
.sim-takte small {
  display: block;
  margin-top: 4px;
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: 0;
  color: var(--sim-grau);
}
@media (max-width: 860px) {
  .sim-vorsatz { font-size: 0.9375rem; }
  .sim-takte { margin-top: 14px; }
}

/* Ein Balken statt Punkten: er zeigt, wie viel Strecke noch kommt. */
.sim-balken {
  margin-top: clamp(14px, 3vh, 28px);
  height: 2px;
  background: var(--sim-linie);
  position: relative;
  overflow: hidden;
}
.sim-balken::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--sim-akzent);
  transform: scaleX(var(--p));
  transform-origin: left center;
}

.sim-fussnote {
  margin: clamp(20px, 3.5vh, 32px) 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--sim-grau);
  max-width: 34em;
}
/* Am Handy zählt jeder Pixel Höhe fürs Telefon. */
@media (max-width: 860px) { .sim-fussnote { display: none; } }

.sim-unsichtbar {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------------------------------------------------------------- Das Gerät */

/* Die Zelle des Telefons ist ein Größen-Container: --sim-w nimmt die Breite, die
   in ihre Höhe UND Breite passt. 0,43 = 430/902 Seitenverhältnis mal 0,9 Luft,
   weil die Drehung das Gerät perspektivisch um bis zu 8 % größer zeichnet. */
.sim-geraet {
  --sim-w: min(100cqw, calc(100cqh * 0.43));
  margin: 0;
  align-self: stretch;
  min-width: 0;
  min-height: 0;
  container-type: size;
  display: grid;
  place-items: center;
  /* Perspektive am Elternteil, damit die Drehung Tiefe hat. Bewusst groß:
     kleine Perspektive verzerrt das Gerät zur Karikatur. */
  perspective: 1400px;
  perspective-origin: 50% 45%;
}

/* iPhone 17 Pro: 402 × 874 pt Bildschirm, rundum 14 pt Rand (2,5 Rahmen, der
   Rest schwarzes Glas), Bildschirmecken 62 pt. Eine Einheit hier = ein pt. */
.sim-telefon {
  --sim-e: calc(var(--sim-w) / 430);
  position: relative;
  width: var(--sim-w);
  aspect-ratio: 430 / 902;
  border-radius: calc(76 * var(--sim-e));
  background: #000;
  box-shadow:
    inset 0 0 0 calc(2.5 * var(--sim-e)) #3A3833;

  /* Die Drehung: von schräg liegend (wie in der Hand) zum Leser hin.
     rotateY -24deg → +6deg, rotateX 10deg → 0deg, dazu ein wenig nach vorn.
     Alles aus derselben Zahl --p. */
  transform:
    rotateY(calc(-24deg + var(--p) * 30deg))
    rotateX(calc(10deg - var(--p) * 10deg))
    translate3d(0, 0, calc(var(--p) * 40px));
  transform-style: preserve-3d;
  will-change: transform;
}

/* Drei Telefone, eines je Ort in der App: Home, das laufende Workout, Analyse.
   Bewegt liegen sie deckungsgleich in derselben Rasterzelle und drehen sich
   gemeinsam; zu sehen ist nur das, in dem die Geschichte gerade spielt (die
   Regeln dazu stehen unten bei „Zustände“). Es sieht aus wie ein Telefon, in
   dem der Bildschirm wechselt. Ohne Bewegung stehen die drei nebeneinander. */
.bewegt .sim-drei > .sim-telefon { grid-area: 1 / 1; }

/* ================================================================ Die App */

.app-schirm {
  --app-grund: #131311;
  --app-flaeche: #1D1C19;
  --app-feld: #26241F;
  --app-rand: #33302A;
  --app-text: #F2F0EB;
  --app-grau: #A29D92;
  --app-akzent: #F0942E;
  --app-auf-akzent: #1C1206;
  --app-gold: #F3CE6B;
  /* iOS-eigen, gemessen: Glasknöpfe der Kopfzeile und die Linie darunter. */
  --app-glas: #1B1B19;
  --app-glas-ring: #393732;
  --app-kopf-linie: #4B4944;

  /* Ein iOS-Punkt. Nur in Kindern benutzen: cqw bezieht sich dort auf diesen
     Bildschirm, am Element selbst auf die Zelle außen. */
  --app-pt: calc(100cqw / 402);
  /* Haarlinie: ein Gerätepixel, wie StyleSheet.hairlineWidth. */
  --app-haar: 0.5px;
  /* Laufweite. iOS gibt SF je Punktgröße ein eigenes Tracking (17 pt enger als
     13 pt). Der Browser nimmt das Tracking der gezeichneten px-Größe, im
     kleinen Telefon also ein zu weites. Die Tabelle ist fast linear, darum ist
     der Ausgleich für jede Schriftgröße derselbe Wert in px. Gemessen gegen die
     CoreText-Breiten der Spezifikation: ±2 % bei 0,5 bis 0,9 px je pt. */
  --app-spur: calc(0.85 * (var(--app-pt) - 1px));

  container-type: inline-size;
  position: absolute;
  inset: calc(14 * var(--sim-e));
  border-radius: calc(62 * var(--sim-e));
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--app-grund);
  color: var(--app-text);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", system-ui, Roboto, "Segoe UI", sans-serif;
  font-variant-numeric: tabular-nums;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: left;
  /* Im Telefon bricht nichts um, bis auf den Fakt in der Pausenkarte. */
  white-space: nowrap;
  user-select: none;
}
/* An den Kindern gesetzt, weil cqw erst dort den Bildschirm meint. */
.app-schirm > * { letter-spacing: var(--app-spur); }

/* Die Zeichen der App (icon.tsx): 24er-Raster, ein Strich von 1,8, runde Enden
   und Ecken, gefärbt wie die Schrift daneben. Die Größe in pt steht in --z. */
.app-z {
  flex: none;
  width: calc(var(--z, 24) * var(--app-pt));
  height: calc(var(--z, 24) * var(--app-pt));
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.app-z-14 { --z: 14; }
.app-z-16 { --z: 16; }
.app-z-20 { --z: 20; }
.app-z-22 { --z: 22; }
.app-z-26 { --z: 26; }
/* Das Löschzeichen ist auf 28 gezeichnet; der Strich wächst mit (1,8 · 28/24). */
.app-z-28er { stroke-width: 2.1; }

/* ------------------------------------------------ Statusleiste und Kopfzeile */
/* Hintergrund #1D1C19 von 0 bis 116 pt, Haarlinie #4B4944 bei 116. */
.app-kopf {
  position: relative;
  flex: none;
  height: calc(116.33 * var(--app-pt));
  background: var(--app-flaeche);
}
.app-kopf::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  border-bottom: var(--app-haar) solid var(--app-kopf-linie);
}
.app-uhr {
  position: absolute;
  left: calc(51 * var(--app-pt));
  top: calc(22.6 * var(--app-pt));
  font-size: calc(17 * var(--app-pt));
  line-height: calc(20 * var(--app-pt));
  font-weight: 600;
  /* Die Systemuhr hat proportionale Ziffern: gemessen 43,2 pt breit. */
  font-variant-numeric: normal;
  color: var(--app-text);
}
.app-insel {
  position: absolute;
  left: calc(138.3 * var(--app-pt));
  top: calc(14 * var(--app-pt));
  width: calc(125.5 * var(--app-pt));
  height: calc(36.5 * var(--app-pt));
  border-radius: calc(18.25 * var(--app-pt));
  background: #000;
}
.app-symbole {
  position: absolute;
  left: calc(288 * var(--app-pt));
  top: calc(26 * var(--app-pt));
  width: calc(80 * var(--app-pt));
  height: calc(13 * var(--app-pt));
  fill: var(--app-text);
  overflow: visible;
}
.app-symbole .app-wlan { fill: none; stroke: var(--app-text); stroke-width: 2.3; }
.app-symbole .app-akku-rand { fill: none; stroke: var(--app-text); stroke-width: 1; opacity: 0.4; }
.app-symbole .app-akku-nase { opacity: 0.4; }

/* Glasknöpfe (iOS 26): Kreis 44,2 pt links, Kapsel rechts, Oberkante 61,8 pt. */
.app-glas {
  position: absolute;
  top: calc(61.8 * var(--app-pt));
  height: calc(44.2 * var(--app-pt));
  border-radius: calc(22.1 * var(--app-pt));
  background: var(--app-glas);
  border: calc(1 * var(--app-pt)) solid var(--app-glas-ring);
  display: flex;
  align-items: center;
  justify-content: center;
}
.app-zurueck { left: calc(15.8 * var(--app-pt)); width: calc(44.2 * var(--app-pt)); }
.app-zurueck svg {
  width: calc(11 * var(--app-pt));
  height: calc(19 * var(--app-pt));
  margin-left: calc(-1.5 * var(--app-pt));
  fill: none;
  stroke: var(--app-text);
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* „Fertig" ist seit dem Neudesign ein gefüllter Knopf (active.tsx: Button sm,
   pill={false}; 32 hoch, Radius 10, 12 seitlich, caption 13/600). iOS 26 legt
   um jedes Element der Kopfzeile weiter seine Glaskapsel: am Store-Bild
   gemessen 69 × 44,2 pt, der Knopf darin 61 × 32. */
.app-fertig {
  right: calc(15.8 * var(--app-pt));
  padding: 0 calc(3 * var(--app-pt));
}
.app-fertig-knopf {
  height: calc(32 * var(--app-pt));
  padding: 0 calc(12 * var(--app-pt));
  display: flex;
  align-items: center;
  border-radius: calc(10 * var(--app-pt));
  background: var(--app-akzent);
  color: var(--app-auf-akzent);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 600;
}
.app-titel {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(61.8 * var(--app-pt));
  height: calc(44.2 * var(--app-pt));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(17 * var(--app-pt));
  font-weight: 600;
}

/* ------------------------------------------------------------------ Leiste */
/* workout-summary-bar.tsx: drei Zahlen mit Beschriftung darüber, zwei Figuren,
   ein Pfeil. Abstand 12, 16 seitlich, 8 oben und unten, Haarlinie darunter; die
   Leiste steht über der Liste und rollt nicht mit. Am Store-Bild 58,5 pt hoch. */
.app-leiste {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  gap: calc(12 * var(--app-pt));
  padding: calc(8 * var(--app-pt)) calc(16 * var(--app-pt));
  color: var(--app-grau);
}
.app-leiste::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  border-bottom: var(--app-haar) solid var(--app-rand);
}
/* Dauer und Sätze nehmen, was ihre Zahl braucht (mindestens 56), das Volumen
   den Rest. */
.app-zahl { flex: none; min-width: calc(56 * var(--app-pt)); display: flex; flex-direction: column; }
.app-zahl-weit { flex: 1 1 0; min-width: 0; }
.app-zahl-kopf {
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 500;
}
/* typeScale.stat: 20/24, 800, Laufweite −0,4 pt. */
.app-zahl-wert {
  color: var(--app-text);
  font-size: calc(20 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
  font-weight: 800;
  letter-spacing: calc(var(--app-spur) - 0.4 * var(--app-pt));
}
/* Zwei Figuren je 22 pt breit mit 2 pt Abstand, in einem Bild (273 : 254). */
.app-figur {
  flex: none;
  display: block;
  width: calc(46 * var(--app-pt));
  height: calc(42.75 * var(--app-pt));
}

/* ---------------------------------------------------------------- Liste */
.app-liste {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
}
/* Die App zieht die Karte beim Öffnen des Keypads animiert nach oben
   (scrollToIndex). Hier dasselbe als transform. Oben 16 pt Rand der Liste und
   12 pt leerer Listenkopf: die erste Karte beginnt bei 28 pt. */
.app-rolle {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: calc(28 * var(--app-pt)) calc(16 * var(--app-pt)) calc(16 * var(--app-pt));
  transition: transform 320ms cubic-bezier(0.25, 0.8, 0.3, 1);
}

/* Karte (card.tsx): im dunklen Schema nur Fläche, kein Rand; Radius 20,
   Innenabstand 16, Kinderabstand 8. */
.app-karte {
  display: flex;
  flex-direction: column;
  gap: calc(8 * var(--app-pt));
  padding: calc(16 * var(--app-pt));
  border-radius: calc(20 * var(--app-pt));
  background: var(--app-flaeche);
}
/* Im Workout stehen die Karten 12 auseinander (Rand je Karte, damit ein
   Supersatz enger rücken kann). */
.app-rolle .app-karte + .app-karte { margin-top: calc(12 * var(--app-pt)); }

.app-karte-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(12 * var(--app-pt));
  color: var(--app-grau);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
}
.app-uebung { color: var(--app-text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; }

/* Chips (button.tsx, sm): 32 hoch, 12 seitlich, caption 13, Fläche #26241F,
   alle gleich leise. Text und Zeichen 8 auseinander. Pille; in der Pausenkarte
   mit Radius 10 (pill={false}). */
.app-chips,
.app-pause-chips {
  display: flex;
  flex-wrap: wrap;
  gap: calc(8 * var(--app-pt));
}
.app-chip {
  display: inline-flex;
  align-items: center;
  gap: calc(8 * var(--app-pt));
  height: calc(32 * var(--app-pt));
  padding: 0 calc(12 * var(--app-pt));
  border-radius: 999px;
  background: var(--app-feld);
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-chip-eckig { border-radius: calc(10 * var(--app-pt)); }

/* Satztabelle: Satz 44 | Zuletzt 68 | kg | Wdh. | Haken 44, Abstand 8. Bei
   338 pt Karteninhalt bleiben für kg und Wdh. je 75 pt. */
.app-spalten {
  display: flex;
  align-items: center;
  gap: calc(8 * var(--app-pt));
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-spalten > span { flex: 1 1 0; text-align: center; }
.app-spalten > span:first-child,
.app-spalten > span:last-child { flex: none; width: calc(44 * var(--app-pt)); text-align: left; }
.app-spalten > span:nth-child(2) { flex: none; width: calc(68 * var(--app-pt)); }

.app-satz {
  display: flex;
  align-items: center;
  gap: calc(8 * var(--app-pt));
}
.app-nr,
.app-feld,
.app-ende,
.app-haken {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Die Satznummer steht ohne Kachel da; eine Kachel trägt nur ein Satz, der
   etwas anderes ist als ein gewöhnlicher (Aufwärmen, Drop). */
.app-nr {
  flex: none;
  width: calc(44 * var(--app-pt));
  height: calc(44 * var(--app-pt));
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 700;
}
/* „Zuletzt": der Wert der letzten Einheit als eine leise Zelle. */
.app-zuletzt {
  flex: none;
  width: calc(68 * var(--app-pt));
  text-align: center;
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
/* Wert: bestätigt fette Schrift ohne Kasten, als Entwurf ein gefüllter Kasten
   mit dem grauen Vorschlag. Immer 2 pt Rand, sonst durchsichtig: so verrutscht
   nichts, wenn das Keypad (orange) oder ein Rekord (gold) ihn färbt. */
.app-feld {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  height: calc(44 * var(--app-pt));
  border: calc(2 * var(--app-pt)) solid transparent;
  border-radius: calc(10 * var(--app-pt));
  color: var(--app-text);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
  font-weight: 700;
}
.app-feld.ist-entwurf { background: var(--app-feld); color: var(--app-grau); font-weight: 400; }
/* Der Haken: Kachel 38 × 38 im 44er-Platz, Radius 10, Zeichen 20. Offen leise
   (Fläche #26241F, helles Zeichen), bestätigt orange gefüllt, beim Rekord gold. */
.app-ende { flex: none; width: calc(44 * var(--app-pt)); }
.app-haken {
  width: calc(38 * var(--app-pt));
  height: calc(38 * var(--app-pt));
  border-radius: calc(10 * var(--app-pt));
  background: var(--app-feld);
  color: var(--app-text);
}
.app-haken.ist-bestaetigt { background: var(--app-akzent); color: var(--app-auf-akzent); }

/* „+ Satz": ein leiser Knopf (chip, md, pill={false}): 44 hoch, Radius 14,
   17 Regular in Grau; 12 pt unter dem letzten Satz. */
.app-knopf {
  height: calc(44 * var(--app-pt));
  margin-top: calc(4 * var(--app-pt));
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: calc(14 * var(--app-pt));
  background: var(--app-feld);
  color: var(--app-grau);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
}

/* Goldlicht über der Rekordzelle (pr-sweep.tsx): ein Streifen, 75 % der Zelle
   breit und mindestens 56 pt, Mitte 75 %, Rand 25 % Deckkraft, einmal quer; die
   Ziffern glimmen dabei golden. Die Zelle ist innen 71 pt breit, der Streifen
   also 56 und sein Weg 127 pt. Hier läuft er am Scrollweg statt an der Uhr.
   Fenster: ab --p 0,519 über 0,048 — muss zu „sim-bestaetigt" in sim.js passen. */
.app-licht {
  --app-t: clamp(0, calc((var(--p) - 0.519) / 0.048), 1);
  position: absolute;
  inset: 0;
  border-radius: calc(8 * var(--app-pt));
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.app-licht-band {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc(56 * var(--app-pt));
  background: linear-gradient(90deg,
    rgba(243, 206, 107, 0) 0%,
    rgba(243, 206, 107, 0.25) 30%,
    rgba(243, 206, 107, 0.75) 50%,
    rgba(243, 206, 107, 0.25) 70%,
    rgba(243, 206, 107, 0) 100%);
  /* inOut-Kurve wie motion.ts, als Smoothstep: t² · (3 − 2t). */
  transform: translate3d(calc((-56 + var(--app-t) * var(--app-t) * (3 - 2 * var(--app-t)) * 127) * var(--app-pt)), 0, 0);
}
.app-licht-ziffern {
  position: relative;
  color: var(--app-gold);
  font-weight: 400;
  opacity: calc(4 * var(--app-t) * (1 - var(--app-t)));
}

/* ------------------------------------------------------- unten: Pause, Keypad */
/* „Pause starten": plain, 44 hoch, 17/600, mittig, 34 pt über der Unterkante. */
.app-ruhe {
  flex: none;
  height: calc(44 * var(--app-pt));
  margin: 0 calc(16 * var(--app-pt)) calc(34 * var(--app-pt));
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--app-akzent);
  font-size: calc(17 * var(--app-pt));
  font-weight: 600;
}

/* Laufende Pause (rest-timer-bar.tsx): eine Karte, Radius 20, 12 pt vom Rand,
   16 innen, ohne Linie. Oben über die ganze Breite die Spur (4 pt), die mit der
   Pause leerläuft. */
.app-pause {
  flex: none;
  margin: 0 calc(12 * var(--app-pt)) calc(34 * var(--app-pt));
  padding: 0 calc(16 * var(--app-pt));
  border-radius: calc(20 * var(--app-pt));
  overflow: hidden;
  background: var(--app-flaeche);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
}
.app-pause-spur {
  height: calc(4 * var(--app-pt));
  margin: 0 calc(-16 * var(--app-pt));
  background: var(--app-rand);
}
/* Rest geteilt durch geplant. Die Pause läuft ab --p 0,582 und steht am Ende
   der Strecke bei 60 von 90 Sekunden, also bei zwei Dritteln — dieselben
   Zahlen wie in sim.js. */
.app-pause-rest {
  display: block;
  height: 100%;
  background: var(--app-akzent);
  transform-origin: left center;
  transform: scaleX(calc(1 - 0.3333 * clamp(0, (var(--p) - 0.582) / 0.418, 1)));
}
.app-pause-zeile {
  min-height: calc(44 * var(--app-pt));
  padding: calc(8 * var(--app-pt)) 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.app-pause-uhr { display: flex; flex-direction: column; }
.app-pause-kopf {
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 500;
}
/* Der Countdown als Zahl: title 28/34, 800, Laufweite −0,8 pt. */
.app-pause-zahl {
  font-size: calc(28 * var(--app-pt));
  line-height: calc(34 * var(--app-pt));
  font-weight: 800;
  letter-spacing: calc(var(--app-spur) - 0.8 * var(--app-pt));
}
.app-pause-schnell { display: flex; align-items: center; gap: calc(4 * var(--app-pt)); }
.app-pause-weiter {
  min-height: calc(44 * var(--app-pt));
  display: flex;
  align-items: center;
  color: var(--app-akzent);
  font-weight: 600;
}
.app-pause-chips { padding-bottom: calc(12 * var(--app-pt)); }
.app-fakt {
  display: flex;
  flex-direction: column;
  gap: calc(4 * var(--app-pt));
  padding: calc(12 * var(--app-pt)) 0;
  border-top: var(--app-haar) solid var(--app-rand);
  white-space: normal;
}
.app-fakt-kopf {
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 600;
}
.app-fakt-weiter {
  align-self: flex-end;
  min-height: calc(32 * var(--app-pt));
  display: flex;
  align-items: center;
  color: var(--app-akzent);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 600;
}

/* Keypad (keypad.tsx): oben Radius 16, Haarlinie, 12 Innenabstand, 8 Abstand.
   Von oben: Zelle und Zahl (title 28/800), die Scheiben-Zeile (36 hoch), zwei
   Schritt-Tasten (44 hoch, Fläche #26241F, 17/600 grau), die Ziffern (48 hoch,
   heading 22/600), unten Abbrechen und doppelt so breit Übernehmen. Reicht wie
   in der App bis an die Unterkante, der Home-Indikator liegt darüber. */
.app-tastatur {
  position: relative;
  flex: none;
  display: flex;
  flex-direction: column;
  gap: calc(8 * var(--app-pt));
  padding: calc(12.33 * var(--app-pt));
  border-radius: calc(16 * var(--app-pt)) calc(16 * var(--app-pt)) 0 0;
  background: var(--app-flaeche);
}
/* Die Haarlinie liegt als Überlagerung über der Fläche, damit ihre Rundung auf
   ganze Pixel die Maße innen nicht verschiebt. */
.app-tastatur::after {
  content: "";
  position: absolute;
  inset: 0;
  border: var(--app-haar) solid var(--app-rand);
  border-radius: inherit;
  pointer-events: none;
}
.app-tast-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(8 * var(--app-pt));
  padding: 0 calc(8 * var(--app-pt));
}
.app-tast-text { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
.app-tast-kontext {
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
}
.app-tast-einheit,
.app-hinweis {
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-anzeige {
  font-size: calc(28 * var(--app-pt));
  line-height: calc(34 * var(--app-pt));
  font-weight: 800;
  letter-spacing: calc(var(--app-spur) - 0.8 * var(--app-pt));
}
/* Die Scheiben-Zeile: links das eine Ende der Stange, gezeichnet, rechts der
   Satz dazu. Immer 36 pt hoch, damit die Tasten beim Tippen nicht springen. */
.app-scheiben {
  height: calc(36 * var(--app-pt));
  padding: 0 calc(8 * var(--app-pt));
  display: flex;
  align-items: center;
  gap: calc(12 * var(--app-pt));
}
.app-hinweis { flex: 1 1 0; min-width: 0; text-align: right; overflow: hidden; }
/* plate-stack.tsx: Stange 22 × 5, Bund 5 × 14, dann die Scheiben vom Bund nach
   außen, die schwerste zuerst, 2 pt auseinander, zuletzt die Hülse 12 × 7.
   Höhe einer Scheibe 12 + √(kg / 25) · 22 pt: 25 kg sind 34, 2,5 kg sind 19.
   Ab 10 kg 9 pt breit und hell, darunter 6 pt und grau. */
.app-stapel { flex: none; height: calc(34 * var(--app-pt)); display: flex; align-items: center; }
.app-stapel > span { flex: none; background: var(--app-rand); }
.app-st-stange {
  width: calc(22 * var(--app-pt));
  height: calc(5 * var(--app-pt));
  border-radius: calc(2 * var(--app-pt)) 0 0 calc(2 * var(--app-pt));
}
.app-st-bund {
  width: calc(5 * var(--app-pt));
  height: calc(14 * var(--app-pt));
  margin-right: calc(2 * var(--app-pt));
  border-radius: calc(1 * var(--app-pt));
}
.app-stapel > .app-st-scheibe {
  width: calc(9 * var(--app-pt));
  height: calc(34 * var(--app-pt));
  margin-right: calc(2 * var(--app-pt));
  border-radius: calc(2 * var(--app-pt));
  background: var(--app-text);
}
.app-stapel > .app-st-klein {
  width: calc(6 * var(--app-pt));
  height: calc(19 * var(--app-pt));
  background: var(--app-grau);
}
.app-st-ende {
  width: calc(12 * var(--app-pt));
  height: calc(7 * var(--app-pt));
  border-radius: 0 calc(2 * var(--app-pt)) calc(2 * var(--app-pt)) 0;
}
.app-tast-reihe { display: flex; gap: calc(8 * var(--app-pt)); }
.app-taste {
  flex: 1 1 0;
  min-height: calc(48 * var(--app-pt));
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: calc(10 * var(--app-pt));
  background: var(--app-grund);
  font-size: calc(22 * var(--app-pt));
  line-height: calc(28 * var(--app-pt));
  font-weight: 600;
  letter-spacing: 0;
}
.app-taste-schritt {
  min-height: calc(44 * var(--app-pt));
  background: var(--app-feld);
  color: var(--app-grau);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
  letter-spacing: var(--app-spur);
}
.app-taste-weg { color: var(--app-grau); }
.app-taste-ok { flex-grow: 2; background: var(--app-akzent); color: var(--app-auf-akzent); }

.app-home {
  position: absolute;
  left: 50%;
  bottom: calc(8 * var(--app-pt));
  width: calc(134 * var(--app-pt));
  height: calc(5 * var(--app-pt));
  margin-left: calc(-67 * var(--app-pt));
  border-radius: calc(2.5 * var(--app-pt));
  background: var(--app-text);
}

/* ================================================= Home und Analyse: Gerüst */
/* Die Tabs der App haben keinen Navigationskopf: oben 62 pt Statusleiste in
   der Farbe der Seite, darunter rollt der Inhalt, und er endet über der Leiste
   des laufenden Workouts und der Tab-Leiste. */
.app-status { position: relative; flex: none; height: calc(62 * var(--app-pt)); }
.app-lauf { display: flex; flex-direction: column; will-change: transform; }

/* Abschnitt: ein Block mit Titel (sectionTitle 19/24, 700, −0,3) und rechts
   daneben, auf derselben Grundlinie, ein leiser Zusatz. */
.app-block { display: flex; flex-direction: column; gap: calc(12 * var(--app-pt)); }
.app-abschnitt {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: calc(12 * var(--app-pt));
}
.app-abschnitt > span:first-child {
  font-size: calc(19 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
  font-weight: 700;
  letter-spacing: calc(var(--app-spur) - 0.3 * var(--app-pt));
}
.app-abschnitt > span + span,
.app-zeile-grau {
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-abschnitt > span + span { font-weight: 500; }
.app-z-18 { --z: 18; }
/* Zeichen, die die App füllt und streicht (flame, play, das Haus im aktiven Tab). */
.app-z-voll { fill: currentColor; }

/* Die Leiste des laufenden Workouts (active-workout-bar.tsx): 50 hoch, Fläche
   #1D1C19, Haarlinie oben. Punkt 8, „Workout" 17/700, die Uhr 17/500 grau,
   rechts die Pause in Orange (nur solange eine läuft) und ein Pfeil. */
.app-mini {
  position: relative;
  flex: none;
  min-height: calc(50 * var(--app-pt));
  padding: 0 calc(16 * var(--app-pt));
  display: flex;
  align-items: center;
  gap: calc(8 * var(--app-pt));
  background: var(--app-flaeche);
  color: var(--app-grau);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
}
.app-mini::before,
.app-tabs::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  border-top: var(--app-haar) solid var(--app-rand);
}
.app-mini-punkt {
  flex: none;
  width: calc(8 * var(--app-pt));
  height: calc(8 * var(--app-pt));
  border-radius: 50%;
  background: var(--app-akzent);
}
.app-mini-name { color: var(--app-text); font-weight: 700; }
.app-mini-uhr { flex: 1 1 0; font-weight: 500; }
.app-mini-pause { color: var(--app-akzent); font-weight: 700; }

/* Tab-Leiste ((tabs)/_layout.tsx): Haarlinie, 49 hoch, darunter 34 für den
   Home-Indikator. Zeichen 24, Beschriftung 10/18, 600; aktiv orange mit
   kräftigerem Strich (2,2 statt 1,8). */
.app-tabs {
  position: relative;
  flex: none;
  display: flex;
  padding-bottom: calc(34 * var(--app-pt));
  background: var(--app-grund);
}
.app-tab {
  flex: 1 1 0;
  min-height: calc(49 * var(--app-pt));
  padding-top: calc(4 * var(--app-pt));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(2 * var(--app-pt));
  color: var(--app-grau);
  font-size: calc(10 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 600;
}
.app-tab.ist-aktiv { color: var(--app-akzent); }
.app-tab.ist-aktiv .app-z { stroke-width: 2.2; }

/* ============================================================ Home („Heute") */
/* (tabs)/index.tsx, während ein Workout läuft. 16 seitlich, 8 oben, Blöcke 24
   auseinander. Im Telefon rollt der Inhalt um 166 pt, bis die Karte
   „Fortschritt" ganz über der Leiste steht (--heim-roll, siehe „Zustände"). */
.app-lauf-heim {
  gap: calc(24 * var(--app-pt));
  padding: calc(8 * var(--app-pt)) calc(16 * var(--app-pt)) calc(32 * var(--app-pt));
  transform: translate3d(0, calc(var(--heim-roll) * -166 * var(--app-pt)), 0);
}

/* Datum und großer Titel (largeTitle 32/36, 800, −1), rechts die Serie. */
.app-titelzeile {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: calc(12 * var(--app-pt));
}
.app-titel-links { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
.app-datum {
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 500;
}
.app-gross {
  font-size: calc(32 * var(--app-pt));
  line-height: calc(36 * var(--app-pt));
  font-weight: 800;
  letter-spacing: calc(var(--app-spur) - 1 * var(--app-pt));
}
.app-serie {
  flex: none;
  min-height: calc(44 * var(--app-pt));
  padding: 0 calc(12 * var(--app-pt));
  display: flex;
  align-items: center;
  gap: calc(4 * var(--app-pt));
  border-radius: calc(16 * var(--app-pt));
  background: var(--app-flaeche);
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-serie .app-z { color: var(--app-akzent); }
.app-serie b {
  color: var(--app-text);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
  font-weight: 800;
}

/* Die Karte oben (next-workout.tsx): ganz in Orange, die einzige farbige
   Fläche des Screens. Zeile 13/600, Titel 28/34, 800, −0,8, darunter der
   dunkle Knopf (52 hoch, Radius 16, 17/700). */
.app-held {
  display: flex;
  flex-direction: column;
  padding: calc(16 * var(--app-pt));
  border-radius: calc(20 * var(--app-pt));
  background: var(--app-akzent);
  color: var(--app-auf-akzent);
}
.app-held-kopf {
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 600;
}
.app-held-titel {
  margin-top: calc(2 * var(--app-pt));
  font-size: calc(28 * var(--app-pt));
  line-height: calc(34 * var(--app-pt));
  font-weight: 800;
  letter-spacing: calc(var(--app-spur) - 0.8 * var(--app-pt));
}
.app-held-knopf {
  min-height: calc(52 * var(--app-pt));
  margin-top: calc(16 * var(--app-pt));
  padding: 0 calc(16 * var(--app-pt));
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(8 * var(--app-pt));
  border-radius: calc(16 * var(--app-pt));
  background: var(--app-auf-akzent);
  color: var(--app-text);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
  font-weight: 700;
}
/* „Routinen": eine Kachel, 46 hoch, Radius 16, Zeichen 18 grau, 17/600. */
.app-kachel {
  min-height: calc(46 * var(--app-pt));
  padding: 0 calc(12 * var(--app-pt));
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(8 * var(--app-pt));
  border-radius: calc(16 * var(--app-pt));
  background: var(--app-flaeche);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
  font-weight: 600;
}
.app-kachel .app-z { color: var(--app-grau); }

/* „Diese Woche" (week-body.tsx): links zwei Figuren je 70 breit, rechts die
   sieben Tage und sechs Muskelgruppen. */
.app-wochenkoerper {
  display: flex;
  align-items: center;
  gap: calc(16 * var(--app-pt));
}
.app-figuren { flex: none; display: flex; gap: calc(4 * var(--app-pt)); }
/* Eine Figur in zwei Schichten: unten alle Muskeln in Ruhe, darüber die
   trainierten in ihrer Farbe. Die obere blendet ein, wenn die Zahlen aufleben. */
.app-koerper {
  position: relative;
  display: block;
  width: calc(70 * var(--app-pt));
  height: calc(136.02 * var(--app-pt));
}
.app-koerper img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.app-wochenseite {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: calc(12 * var(--app-pt));
}
/* Tage: zwei Buchstaben (11/18, 600), darunter ein Punkt von 10. Trainiert
   orange, sonst Fläche #26241F; heute steht der Tag in heller Schrift. */
.app-tage { display: flex; justify-content: space-between; }
.app-tag {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(4 * var(--app-pt));
  color: var(--app-grau);
  font-size: calc(11 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 600;
}
.app-tag.ist-heute { color: var(--app-text); }
.app-tag i {
  width: calc(10 * var(--app-pt));
  height: calc(10 * var(--app-pt));
  border-radius: 50%;
  background: var(--app-feld);
}
.app-tag.ist-trainiert i { background: var(--app-akzent); }
/* Gruppen: Name (76 breit, 13/500), Spur 5 hoch, Zahl (13/700, rechts). Die
   Füllung ist Sätze geteilt durch die meisten Sätze der Woche. */
.app-gruppen { display: flex; flex-direction: column; gap: calc(4 * var(--app-pt)); }
.app-gruppe {
  min-height: calc(22 * var(--app-pt));
  display: flex;
  align-items: center;
  gap: calc(8 * var(--app-pt));
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-gruppe-name { flex: none; width: calc(76 * var(--app-pt)); font-weight: 500; }
.app-gruppe-spur {
  flex: 1 1 0;
  height: calc(5 * var(--app-pt));
  border-radius: 999px;
  overflow: hidden;
  background: var(--app-feld);
}
.app-gruppe-spur i {
  display: block;
  width: calc(var(--anteil) * 100%);
  height: 100%;
  border-radius: 999px;
  background: var(--app-text);
}
.app-gruppe-zahl { flex: none; min-width: calc(26 * var(--app-pt)); text-align: right; font-weight: 700; }

/* „Fortschritt" (progress-card.tsx): die Zahl der laufenden Woche (28/34,
   800), daneben die letzte, darunter acht Balken. Ein Balken ist Wert durch
   den größten mal 84 pt; der letzte, die laufende Woche, ist orange. */
.app-fortkarte { gap: calc(12 * var(--app-pt)); }
.app-fort-kopf {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: calc(12 * var(--app-pt));
}
.app-fort-zahl {
  font-size: calc(28 * var(--app-pt));
  line-height: calc(34 * var(--app-pt));
  font-weight: 800;
  letter-spacing: calc(var(--app-spur) - 0.8 * var(--app-pt));
}
.app-fort-vor {
  flex-shrink: 1;
  text-align: right;
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 500;
}
.app-balkenreihe {
  height: calc(84 * var(--app-pt));
  display: flex;
  align-items: flex-end;
  gap: calc(8 * var(--app-pt));
}
.app-balken { flex: 1 1 0; height: 100%; display: flex; align-items: flex-end; overflow: hidden; }
.app-balken i {
  display: block;
  width: 100%;
  height: calc(var(--hoehe) * 100%);
  border-radius: calc(6 * var(--app-pt)) calc(6 * var(--app-pt)) calc(2 * var(--app-pt)) calc(2 * var(--app-pt));
  background: var(--app-rand);
}
.app-balken:last-child i { background: var(--app-akzent); }
.app-wochennummern {
  margin-top: calc(4 * var(--app-pt));
  display: flex;
  gap: calc(8 * var(--app-pt));
  color: var(--app-grau);
  font-size: calc(11 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
  font-weight: 600;
  text-align: center;
}
.app-wochennummern span { flex: 1 1 0; }
.app-wochennummern span:last-child { color: var(--app-text); }

/* ---- Aufleben. In der App stehen Home und Analyse still; hochzählende Zahlen
   und eine Figur, die aufleuchtet, kennt sie vom Abschluss-Screen (900 ms,
   easeOutCubic). Hier lebt die Woche auf, während das Telefon hereinkommt, und
   der Fortschritt, wenn seine Karte hereinrollt: Füllungen und Balken fahren
   herein, die trainierten Muskeln blenden ein, die Zahlen zählt sim.js. */
.app-woche .app-koerper-licht { opacity: var(--heim-woche); }
.app-woche .app-gruppe-spur i { transform: translate3d(calc((var(--heim-woche) - 1) * 100%), 0, 0); }
.app-fort .app-balken i { transform: translate3d(0, calc((1 - var(--heim-fort)) * 100%), 0); }

/* ================================================================== Analyse */
/* (tabs)/analytics.tsx: Karten 16 auseinander, 16 seitlich. Der Tab beginnt in
   der App mit Titel, Serie und Kalender; hier steht er schon gerollt da, die
   Karte „Muskelverteilung" oben (so zeigt ihn auch das Store-Bild). Sie ist
   662 pt hoch und füllt den Platz zwischen Statusleiste und Workout-Leiste.
   Dann rollt der Inhalt um 678 pt zur „Muskel-Heatmap" (--ana-roll). */
.app-lauf-analyse {
  gap: calc(16 * var(--app-pt));
  padding: calc(8 * var(--app-pt)) calc(16 * var(--app-pt)) calc(64 * var(--app-pt));
  transform: translate3d(0, calc(var(--ana-roll) * -678 * var(--app-pt)), 0);
}
/* Karte eines Widgets (card.tsx): Kinderabstand 12, Titel 17/24, 700. */
.app-wkarte { gap: calc(12 * var(--app-pt)); }
.app-karte-titel {
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
  font-weight: 700;
}
/* Zeitraum (range-picker.tsx): 44 hoch, links leise das Wort, rechts der
   gewählte Zeitraum in Orange und ein Pfeil. */
.app-zeitraum {
  min-height: calc(44 * var(--app-pt));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(12 * var(--app-pt));
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-zeitraum > span + span {
  display: flex;
  align-items: center;
  gap: calc(8 * var(--app-pt));
  color: var(--app-akzent);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
}
.app-zeitraum .app-z { color: var(--app-grau); }
.app-widget { display: flex; flex-direction: column; gap: calc(8 * var(--app-pt)); }

/* Netz (radar-chart.tsx): 300 × 300 mittig, 4 pt Rand oben und unten. Raster
   #33302A, Strich zwei Haarlinien. Die Fläche des Zeitraums orange (Strich
   2,5, Füllung 28 %), die des Zeitraums davor grau (Strich 2, Füllung 18 %):
   im Beispiel fast nichts, ein Punkt in der Mitte. Achsen 13/18 grau. */
.app-netzfeld {
  position: relative;
  align-self: center;
  width: calc(300 * var(--app-pt));
  height: calc(300 * var(--app-pt));
  margin: calc(4 * var(--app-pt)) 0;
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-netz { position: absolute; inset: 0; display: block; width: 100%; height: 100%; overflow: visible; }
.app-netz-raster { fill: none; stroke: var(--app-rand); stroke-width: 0.667; }
.app-netz-vorher { fill: rgba(162, 157, 146, 0.18); stroke: var(--app-grau); stroke-width: 2; stroke-linejoin: round; }
.app-netz-jetzt { fill: rgba(240, 148, 46, 0.28); stroke: var(--app-akzent); stroke-width: 2.5; stroke-linejoin: round; }
.app-netzfeld > span { position: absolute; width: calc(88 * var(--app-pt)); text-align: center; }

/* Legende: zwei Einträge 16 auseinander, Punkt 10, zwei Zeilen 13/18. */
.app-legende {
  display: flex;
  justify-content: center;
  gap: calc(16 * var(--app-pt));
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-legende > span { display: flex; align-items: center; gap: calc(4 * var(--app-pt)); }
.app-legende i,
.app-tag i { flex: none; }
.app-legende i {
  width: calc(10 * var(--app-pt));
  height: calc(10 * var(--app-pt));
  border-radius: 50%;
  background: var(--app-akzent);
}
.app-legende i.app-legende-grau { background: var(--app-grau); }
/* Die Systemschrift setzt Tabellenziffern weiter als die proportionalen. */
.app-schirm-analyse .app-legende > span > span { font-variant-numeric: normal; }
.app-schirm-analyse .app-tab-ziffern { font-variant-numeric: tabular-nums; }

/* Die vier Kennzahlen (stat-widgets.tsx): zwei je Zeile, 8 auseinander, links
   eine Linie von 2 pt. Zahl 20/24, 800; Name 13/18 grau; darunter die
   Veränderung zum Zeitraum davor, grün, wenn es mehr ist. */
.app-kennzahlen { display: flex; flex-wrap: wrap; gap: calc(8 * var(--app-pt)); }
.app-kennzahl {
  flex: 1 1 48%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--app-pt));
  padding: calc(4 * var(--app-pt)) 0 calc(4 * var(--app-pt)) calc(12 * var(--app-pt));
  border-left: calc(2 * var(--app-pt)) solid var(--app-rand);
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-kennzahl b {
  color: var(--app-text);
  font-size: calc(20 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
  font-weight: 800;
  letter-spacing: calc(var(--app-spur) - 0.4 * var(--app-pt));
}
.app-kennzahl-delta { color: #66B36E; }

/* „Was zeigt das?" (info-button.tsx): Kreis 18 mit dem Buchstaben i, 13/18 orange. */
.app-info {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: calc(4 * var(--app-pt));
  color: var(--app-akzent);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-info i {
  width: calc(18 * var(--app-pt));
  height: calc(18 * var(--app-pt));
  display: flex;
  align-items: center;
  justify-content: center;
  border: calc(1 * var(--app-pt)) solid var(--app-akzent);
  border-radius: 50%;
  font-style: normal;
  font-size: calc(11 * var(--app-pt));
  line-height: calc(13 * var(--app-pt));
  font-weight: 600;
}

/* Umschalter (segmented.tsx): Spur #26241F, Radius 16, innen 3; das gewählte
   Feld #33302A, Radius 12, 17/600. */
.app-segmente {
  display: flex;
  gap: calc(2 * var(--app-pt));
  padding: calc(3 * var(--app-pt));
  border-radius: calc(16 * var(--app-pt));
  background: var(--app-feld);
  color: var(--app-grau);
  font-size: calc(17 * var(--app-pt));
  line-height: calc(24 * var(--app-pt));
}
.app-segmente span {
  flex: 1 1 0;
  min-height: calc(38 * var(--app-pt));
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: calc(12 * var(--app-pt));
}
.app-segmente .ist-gewaehlt { background: var(--app-rand); color: var(--app-text); font-weight: 600; }

/* Die Figur der Heatmap: eine, 190 breit, mittig. */
.app-koerper-gross {
  align-self: center;
  width: calc(190 * var(--app-pt));
  height: calc(369.21 * var(--app-pt));
}
/* Skala: fünf Stufen der Wärme (heatColor bei 0, 0,25, 0,5, 0,75, 1). */
.app-skala {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(8 * var(--app-pt));
  color: var(--app-grau);
  font-size: calc(13 * var(--app-pt));
  line-height: calc(18 * var(--app-pt));
}
.app-skala-stufen { display: flex; gap: calc(2 * var(--app-pt)); }
.app-skala-stufen i {
  width: calc(22 * var(--app-pt));
  height: calc(10 * var(--app-pt));
  border-radius: calc(2 * var(--app-pt));
  background: #33302A;
}
.app-skala-stufen i:nth-child(2) { background: #6F5133; }
.app-skala-stufen i:nth-child(3) { background: #986735; }
.app-skala-stufen i:nth-child(4) { background: #C37D34; }
.app-skala-stufen i:nth-child(5) { background: #F0942E; }

/* ---- Aufleben, wie auf Home eine Zugabe dieser Seite: das Netz wächst aus
   der Mitte, wenn der Tab aufgeht, die Figur leuchtet auf, wenn ihre Karte
   hereingerollt ist. */
.app-netz-form { transform-origin: 150px 150px; transform: scale(var(--ana-netz)); }
.app-heat .app-koerper-licht { opacity: var(--ana-heat); }

/* ---------------------------------------------------------------- Zustände */
/* Das HTML trägt alle Schritt-Klassen, also den Endzustand. sim.js nimmt sie für
   frühere Takte weg; jede Regel hier beschreibt ein „noch nicht".
     sim-training     das laufende Workout ist offen (vorher: Home)
     sim-offen        Keypad auf dem kg-Feld von Satz 2
     sim-7, sim-5     die getippten Ziffern
     sim-uebernommen  Keypad-Haken: 75 steht fett im Feld
     sim-bestaetigt   Zeilen-Haken: Satz bestätigt, Rekord
     sim-pause        die Pause läuft (Karte im Workout, Leiste in den Tabs)
     sim-zurueck      zurück in den Tabs: wieder Home
     sim-analyse      der Tab Analyse
   Kurz gedrückt: sim-druck-leiste, sim-druck-7, sim-druck-5, sim-druck-haken,
   sim-druck-zurueck. Ein Tab hat in der App keinen gedrückten Zustand. */

/* Fenster für das, was auf Home und Analyse rollt und auflebt. Die Zähler in
   sim.js nehmen dieselben Fenster aus dem HTML (data-ab, data-ueber).
   Kurven: easeOutCubic wie in der App, fürs Rollen ein Smoothstep.
   Home: die Woche lebt während der Anfahrt auf (--a ab 0,68), damit das
   Telefon nicht mit leeren Balken hereinkommt; gerollt wird ab --p 0,04, der
   Fortschritt lebt ab 0,075 auf. */
.sim-stand {
  --hw: clamp(0, calc((var(--a) - 0.68) / 0.32), 1);
  --heim-woche: calc(1 - (1 - var(--hw)) * (1 - var(--hw)) * (1 - var(--hw)));
  --hr: clamp(0, calc((var(--p) - 0.04) / 0.08), 1);
  --heim-roll: calc(var(--hr) * var(--hr) * (3 - 2 * var(--hr)));
  --hf: clamp(0, calc((var(--p) - 0.075) / 0.055), 1);
  --heim-fort: calc(1 - (1 - var(--hf)) * (1 - var(--hf)) * (1 - var(--hf)));
  /* Analyse: das Netz ab 0,76, das Rollen ab 0,84, die Figur ab 0,91. */
  --an: clamp(0, calc((var(--p) - 0.76) / 0.06), 1);
  --ana-netz: calc(1 - (1 - var(--an)) * (1 - var(--an)) * (1 - var(--an)));
  --ar: clamp(0, calc((var(--p) - 0.84) / 0.1), 1);
  --ana-roll: calc(var(--ar) * var(--ar) * (3 - 2 * var(--ar)));
  --ah: clamp(0, calc((var(--p) - 0.91) / 0.07), 1);
  --ana-heat: calc(1 - (1 - var(--ah)) * (1 - var(--ah)) * (1 - var(--ah)));
}

/* Welches der drei Telefone zu sehen ist. Nur bewegt: ohne Bewegung stehen
   alle drei nebeneinander. Unsichtbar statt entfernt, damit beim Wechsel
   nichts neu ausgelegt werden muss. */
.bewegt .sim-stand.sim-training:not(.sim-zurueck) .sim-tel-heim,
.bewegt .sim-stand.sim-analyse .sim-tel-heim,
.bewegt .sim-stand:not(.sim-training) .sim-tel-training,
.bewegt .sim-stand.sim-zurueck .sim-tel-training,
.bewegt .sim-stand:not(.sim-analyse) .sim-tel-analyse { visibility: hidden; }

.app-tastatur,
.app-ruhe,
.app-wert-vorschlag,
.app-s1,
.app-a0, .app-a1,
.app-h0, .app-h1 { display: none; }

/* Endzustand von Satz 2: beide Werte fett ohne Kasten, das Rekordfeld mit
   Goldrand, der Haken gold gefüllt. */
.app-wert-vorschlag { color: var(--app-grau); font-weight: 400; }
.app-feld-kg { border-color: var(--app-gold); }
.app-satz-2 .app-haken { background: var(--app-gold); color: var(--app-auf-akzent); }

/* Vor dem Keypad-Haken: grauer Vorschlag im Feld. */
.sim-stand:not(.sim-uebernommen) .app-wert-vorschlag { display: inline; }
.sim-stand:not(.sim-uebernommen) .app-wert-neu { display: none; }

/* Vor dem Zeilen-Haken: Satz 2 ist ein Entwurf. Beide Felder im Kasten, Wdh.
   grau, der Haken leise, kein Goldrand; in der Leiste steht erst ein Satz. */
.sim-stand:not(.sim-bestaetigt) .app-satz-2 .app-feld { background: var(--app-feld); }
.sim-stand:not(.sim-bestaetigt) .app-feld-kg { border-color: transparent; }
.sim-stand:not(.sim-bestaetigt) .app-feld-wdh { color: var(--app-grau); font-weight: 400; }
.sim-stand:not(.sim-bestaetigt) .app-satz-2 .app-haken { background: var(--app-feld); color: var(--app-text); }
.sim-stand.sim-druck-haken .app-satz-2 .app-haken { opacity: 0.7; }
.sim-stand.sim-druck-zurueck .sim-tel-training .app-zurueck { background: var(--app-glas-ring); }
.sim-stand:not(.sim-bestaetigt) .app-s1 { display: inline; }
.sim-stand:not(.sim-bestaetigt) .app-s2 { display: none; }

/* Ohne laufende Pause: „Pause starten" statt der Karte. */
.sim-stand:not(.sim-pause) .app-pause,
.sim-stand:not(.sim-pause) .app-mini-pause { display: none; }
.sim-stand.sim-druck-leiste .sim-tel-heim .app-mini { background: var(--app-feld); }
.sim-stand:not(.sim-pause) .app-ruhe { display: flex; }

/* Keypad offen: Rand orange, die Karte an die Oberkante der Liste, unten nur
   das Keypad. */
.sim-stand.sim-offen:not(.sim-uebernommen) .app-tastatur { display: flex; }
.sim-stand.sim-offen:not(.sim-uebernommen) .app-ruhe { display: none; }
.sim-stand.sim-offen:not(.sim-uebernommen) .app-feld-kg { border-color: var(--app-akzent); }
.sim-stand.sim-offen:not(.sim-uebernommen) .app-rolle { transform: translate3d(0, calc(-28 * var(--app-pt)), 0); }

/* Anzeige und Scheiben-Zeile: „–" und nur die Stange, dann „7" (weniger als
   die Stange, noch keine Scheibe), dann „75" mit 25 und 2,5. */
.sim-stand:not(.sim-7) .app-a0,
.sim-stand:not(.sim-7) .app-h0 { display: inline; }
.sim-stand.sim-7:not(.sim-5) .app-a1,
.sim-stand.sim-7:not(.sim-5) .app-h1 { display: inline; }
.sim-stand:not(.sim-5) .app-a2,
.sim-stand:not(.sim-5) .app-h2,
.sim-stand:not(.sim-5) .app-st-scheibe { display: none; }
.sim-stand.sim-druck-7 .app-taste-7,
.sim-stand.sim-druck-5 .app-taste-5 { background: var(--app-feld); }

/* ---------------------------------------------------- Ohne Skript, ohne Bewegung */
/* Ohne Skript steht --p auf 1 und alle Schritt-Klassen stehen im HTML: das
   Telefon zeigt den Endzustand, die Takte liegen als Liste untereinander. */
:is(.no-js, .ruhig) .sim-strecke { height: auto; }
:is(.no-js, .ruhig) .sim-buehne { position: static; height: auto; grid-template-rows: auto; padding-block: clamp(48px, 9vh, 96px); }
:is(.no-js, .ruhig) .sim-geraet { container-type: normal; align-self: center; --sim-w: min(340px, 80vw); }
:is(.no-js, .ruhig) .sim-telefon { transform: none; }
:is(.no-js, .ruhig) .sim-takte { gap: 16px; }
:is(.no-js, .ruhig) .sim-takte li { grid-area: auto; opacity: 1; transform: none; }
:is(.no-js, .ruhig) .sim-balken,
:is(.no-js, .ruhig) .sim-vorsatz { display: none; }
:is(.no-js, .ruhig) .sim-fussnote { display: block; }
/* GingR ohne Bewegung: die drei Telefone nebeneinander, links daneben die
   Takte als Liste. Jeder Screen steht an seinem Anfang, nicht gerollt. Unter
   1100 px einspaltig: erst der Text, darunter die drei in einer Reihe; unter
   701 px wird daraus eine Reihe zum Wischen. */
:is(.no-js, .ruhig) .sim-drei {
  --sim-w: min(246px, calc((100vw - 2 * var(--pad, 40px) - 22rem - 88px) / 3));
  display: flex;
  justify-content: flex-end;
  gap: 20px;
  perspective: none;
}
:is(.no-js, .ruhig) .sim-drei > .sim-telefon { flex: none; }
:is(.no-js, .ruhig) #gingr .sim-buehne { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); }
:is(.no-js, .ruhig) .sim-drei :is(.app-lauf-heim, .app-lauf-analyse) { transform: none; }
@media (max-width: 1099px) {
  :is(.no-js, .ruhig) #gingr .sim-buehne { grid-template-columns: minmax(0, 1fr); }
  :is(.no-js, .ruhig) .sim-drei {
    --sim-w: min(300px, calc((100vw - 2 * var(--pad, 40px) - 40px) / 3));
    justify-content: center;
  }
}
@media (max-width: 700px) {
  :is(.no-js, .ruhig) .sim-drei {
    --sim-w: min(300px, 72vw);
    justify-content: flex-start;
    gap: 16px;
    margin-inline: calc(-1 * var(--pad, 20px));
    padding-inline: var(--pad, 20px);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--pad, 20px);
    scrollbar-width: none;
  }
  :is(.no-js, .ruhig) .sim-drei > .sim-telefon { scroll-snap-align: start; }
}

@media (prefers-reduced-motion: reduce) {
  /* Kein Drehen, kein Ein- und Ausblenden: der Endzustand steht sofort da.
     sim.js tut dann nichts außer no-js zu entfernen. */
  .sim-strecke { height: auto; }
  .sim-buehne { position: static; height: auto; grid-template-rows: auto; padding-block: clamp(48px, 9vh, 96px); }
  .sim-geraet { container-type: normal; align-self: center; --sim-w: min(340px, 80vw); }
  .sim-telefon { transform: none; }
  .sim-takte { gap: 16px; }
  .sim-takte li { grid-area: auto; opacity: 1; transform: none; transition: none; }
  .sim-balken,
  .sim-vorsatz { display: none; }
  .sim-fussnote { display: block; }
  .app-rolle { transition: none; }
  /* GingR: dieselben Regeln wie oben unter .ruhig. */
  .sim-drei {
    --sim-w: min(246px, calc((100vw - 2 * var(--pad, 40px) - 22rem - 88px) / 3));
    display: flex;
    justify-content: flex-end;
    gap: 20px;
    perspective: none;
  }
  .sim-drei > .sim-telefon { flex: none; grid-area: auto; visibility: visible; }
  #gingr .sim-buehne { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); }
  .sim-drei :is(.app-lauf-heim, .app-lauf-analyse) { transform: none; }
}
@media (prefers-reduced-motion: reduce) and (max-width: 1099px) {
  #gingr .sim-buehne { grid-template-columns: minmax(0, 1fr); }
  .sim-drei {
    --sim-w: min(300px, calc((100vw - 2 * var(--pad, 40px) - 40px) / 3));
    justify-content: center;
  }
}
@media (prefers-reduced-motion: reduce) and (max-width: 700px) {
  .sim-drei {
    --sim-w: min(300px, 72vw);
    justify-content: flex-start;
    gap: 16px;
    margin-inline: calc(-1 * var(--pad, 20px));
    padding-inline: var(--pad, 20px);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--pad, 20px);
    scrollbar-width: none;
  }
  .sim-drei > .sim-telefon { scroll-snap-align: start; }
}

/* ------------------------------------------------------------- Handy quer */
/* Wenig Höhe, viel Breite: gestapelt wäre das Telefon keine 90 px breit.
   Deshalb zweispaltig wie am Computer, ohne die Unterzeilen der Takte. Unter
   500 px Höhe gilt ohnehin die ruhige Fassung (Klasse ruhig); die Spalte des
   Telefons nimmt dann dessen feste Breite. */
@media (max-width: 860px) and (orientation: landscape) and (max-height: 500px) {
  .sim-buehne {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: minmax(0, 1fr);
    align-items: center;
    gap: 24px;
    padding-block: 12px;
  }
  /* Nur beim Rezeptbuch: GingR steht in der ruhigen Fassung einspaltig (Text,
     darunter die drei Telefone zum Wischen) und behält seine Unterzeilen. */
  .sim-rezept .sim-takte small { display: none; }
}
