/* ============================================================
   nilo Display-Vorschau (nur Startseite)
   Nachbildung des runden 466-px-Displays aus firmware/src/rep12_ui.cpp,
   Stand Firmware 1.9.22 (Commit 8396358, intern, Branch
   claude/zellalgorithmus-bewegungsrichtung-5y3mwd, nicht auf main).
   Alle Masse stehen in Geräte-Pixeln (Panel 466 x 466) und werden über
   --px auf die tatsächliche Breite skaliert. Positionen wie in der Firmware
   (Mittelpunkte und Kanten aus build_main_screen, build_menu_screen,
   verlauf_satzzeile, uebung_build_locked, repcheck_build_locked,
   ui_show_quality_popup), nichts in Ecken: der Bildschirm ist rund.
   Farben nur über --rep-* Tokens. Ausnahme in der Abweichung: der gedämpfte
   Text des Geräts ist #A3A3A3, hier --rep-text-muted (#8A8A8A), weil es dafür
   kein Token gibt.
   Schrift wie am Gerät: LVGL-Montserrat, nur ein Gewicht (400), in den
   Grössen, die rep12_ui.cpp je Element setzt. Die grossen Ziffern sind keine
   Montserrat, sondern die Bitmapschrift digital_240 (Zähler) und digital_80
   (Uhr im Menü), siehe .dp__d. digital_80 gibt es hier nicht als eigenes
   Bild: der Streifen von digital_240 ist auf Zellbreite 41 und Höhe 51 skaliert
   (Näherung, Strichstärke kann vom Gerät abweichen). Montserrat steht als
   einzige Ausnahme von den Hausschriften hier, ausdrücklich in
   design/check_tokens.py erlaubt.
   ============================================================ */

.dp { display: flex; flex-direction: column; align-items: center; gap: 18px; }

.dp__frame {
  width: min(100%, 360px);
  aspect-ratio: 1;
  box-sizing: border-box;
  padding: 6px;
  border-radius: 50%;
  background: var(--rep-surface-3);
  border: 1px solid var(--rep-border-strong);
  box-shadow: var(--rep-shadow);
}

.dp__screen {
  --px: calc(360px / 466);
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  /* clip statt hidden: kein Scroll-Container. Mit hidden schob focus() auf eine
   * ausgeschobene Ansicht den Bildschirm um bis zu 360 px nach links. */
  overflow: clip;
  background: var(--rep-bg);
  color: var(--rep-text);
  container-type: inline-size;
  font-family: "Montserrat", sans-serif;
  font-weight: 400;
  font-synthesis: none;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
@supports (width: 1cqw) {
  .dp__screen { --px: calc(100cqw / 466); }
}

/* Drei Ansichten nebeneinander: Menü links, Zähler Mitte, Verlauf rechts.
 * Die Bewegung ist kurz und mechanisch (am Gerät MOVE_LEFT und MOVE_RIGHT). */
.dp__view {
  position: absolute;
  inset: 0;
  background: var(--rep-bg);
  transition: transform var(--rep-duration-mid) var(--rep-ease-out);
}
.dp__menu { transform: translateX(-100%); }
.dp__screen[data-screen="menu"] .dp__menu { transform: none; }
.dp__screen[data-screen="menu"] .dp__home { transform: translateX(100%); }
.dp__verlauf { transform: translateX(100%); }
.dp__screen[data-screen="verlauf"] .dp__verlauf { transform: none; }
.dp__screen[data-screen="verlauf"] .dp__home { transform: translateX(-100%); }
/* Übungswahl und Wdh.-Abfrage laden am Gerät ohne Animation (lv_scr_load). */
.dp__ue, .dp__rc { transition: none; }

/* Mittelpunkt-Platzierung: --y ist die Höhe der Elementmitte in Geräte-Pixeln. */
.dp__at {
  position: absolute;
  left: 50%;
  top: calc(var(--y) * var(--px));
  transform: translate(-50%, -50%);
  text-align: center;
  white-space: nowrap;
  width: max-content;
}

/* ── Zähler-Ansicht ── */

/* Zwölf Randpunkte, 14 px, Bahnradius 212, Punkt 0 oben, im Uhrzeigersinn. */
.dp__d14 {
  position: absolute;
  left: calc((var(--cx) - 7) * var(--px));
  top: calc((var(--cy) - 7) * var(--px));
  width: calc(14 * var(--px));
  height: calc(14 * var(--px));
  border-radius: 50%;
  background: var(--rep-border-strong);
}
.dp__d14.is-on { background: var(--rep-accent); }
.dp__d14.is-red { background: var(--rep-score-poor); }

.dp__go {
  position: absolute;
  top: calc(52 * var(--px));
  left: calc(118 * var(--px));
  width: calc(230 * var(--px));
  height: max(calc(70 * var(--px)), 44px);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(14 * var(--px));
  padding: 0;
  border: 0;
  border-radius: calc(35 * var(--px));
  background: var(--rep-accent);
  color: var(--rep-on-accent);
  font-family: inherit;
  font-weight: 400;
  font-size: calc(28 * var(--px));
  cursor: pointer;
  transition: transform var(--rep-duration-fast) var(--rep-ease-out),
              background var(--rep-duration-fast) var(--rep-ease);
}
/* Läuft: rote STOP-Pille, dunkle Tinte auch auf Rot (Artboard B2, seit 1.9.17). */
.dp__home.is-running .dp__go { background: var(--rep-score-poor); }
.dp__go:active { transform: scale(.98); }
.dp__sym { width: calc(30 * var(--px)); height: calc(30 * var(--px)); flex: none; }
.dp__sym--stop { display: none; }
.dp__home.is-running .dp__sym--play { display: none; }
.dp__home.is-running .dp__sym--stop { display: block; }

/* Ziffern: 1-bpp-Bitmap, Ziffern 0 bis 9 als Streifen (assets/digital240.png,
 * erzeugt von tools/digital240_sprite.py), Zelle 117 px, Zeile 151 px. Jede Ziffer
 * steht wie am Gerät in einer Zelle fester Breite (116 px, count_zeigen_locked);
 * die «1» wird mit --sh nach rechts auf den rechten Rand der «8» geschoben
 * (zf_shift). Die Geisterziffern «88» liegen dahinter. */
.dp__cnt, .dp__clk { position: absolute; inset: 0; pointer-events: none; }
.dp__d {
  position: absolute;
  top: calc(var(--top) * var(--px));
  left: calc((var(--x) + var(--sh, 0)) * var(--px));
  width: calc(117 * var(--px));
  height: calc(151 * var(--px));
  background: var(--rep-text-muted);
  -webkit-mask: url(/assets/digital240.png) calc(var(--i) * -117 * var(--px)) 0 / calc(1170 * var(--px)) calc(151 * var(--px)) no-repeat;
  mask: url(/assets/digital240.png) calc(var(--i) * -117 * var(--px)) 0 / calc(1170 * var(--px)) calc(151 * var(--px)) no-repeat;
}
.dp__d--ghost { background: var(--rep-surface-2); }
.dp__home.is-running .dp__d:not(.dp__d--ghost) { background: var(--rep-accent); }
/* Uhr im Menü: digital_80, Zelle 41 x 51. */
.dp__d--clk {
  width: calc(41.3 * var(--px));
  height: calc(51 * var(--px));
  background: var(--rep-text);
  -webkit-mask-size: calc(413 * var(--px)) calc(51 * var(--px));
  -webkit-mask-position: calc(var(--i) * -41.3 * var(--px)) 0;
  mask-size: calc(413 * var(--px)) calc(51 * var(--px));
  mask-position: calc(var(--i) * -41.3 * var(--px)) 0;
}
.dp__d--clk.dp__d--ghost { background: var(--rep-surface-2); }
/* Doppelpunkt: zwei 6 x 6 Quadrate (CLK_KOLON_D), weiss bei gestellter Uhr. */
.dp__kolon {
  position: absolute;
  left: calc(230 * var(--px));
  width: calc(6 * var(--px));
  height: calc(6 * var(--px));
  border-radius: 1px;
  background: var(--rep-text);
}

/* Übungspille: 280 x 44, Name und Chevron als Gruppe in der Mitte. Läuft ein
 * Satz, bleibt nur der Name, gedämpft, ohne Füllung und ohne Chevron (B2). */
.dp__pill {
  position: absolute;
  left: calc(93 * var(--px));
  top: calc(322 * var(--px));
  width: calc(280 * var(--px));
  height: max(calc(44 * var(--px)), 44px);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(6 * var(--px));
  padding: 0;
  border: 0;
  border-radius: calc(22 * var(--px));
  background: var(--rep-surface-2);
  color: var(--rep-text);
  font-family: inherit;
  font-weight: 400;
  font-size: calc(24 * var(--px));
  line-height: 1;
  cursor: pointer;
}
.dp__pill:active { background: var(--rep-border-strong); }
.dp__chev { width: calc(22 * var(--px)); height: calc(22 * var(--px)); color: var(--rep-text-muted); flex: none; }
.dp__home.is-running .dp__pill { background: transparent; color: var(--rep-text-muted); cursor: default; pointer-events: none; }
.dp__home.is-running .dp__chev { display: none; }

/* Unsichtbare Tippflächen am linken und rechten Rand (70 x 320 + 16 px Zusatz),
 * links das Menü, rechts den Verlauf (im Satz tut der rechte Streifen nichts). */
.dp__edge {
  position: absolute;
  top: calc(73 * var(--px));
  width: calc(70 * var(--px));
  height: calc(320 * var(--px));
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.dp__edge--l { left: 0; }
.dp__edge--r { right: 0; }
.dp__edge::after { content: ""; position: absolute; inset: calc(-16 * var(--px)); }

/* ── Menü-Ansicht ── */
.dp__ring {
  position: absolute;
  box-sizing: border-box;
  display: grid;
  place-items: center;
  transform: translate(-50%, -50%);
  top: calc(66 * var(--px));
  border-radius: 50%;
  border: calc(3 * var(--px)) solid var(--rep-border-strong);
  background: var(--rep-bg);
}
.dp__ring svg { width: 52%; height: 52%; display: block; }
.dp__ring--set { left: calc(233 * var(--px)); width: calc(72 * var(--px)); height: calc(72 * var(--px)); border-color: var(--rep-accent); color: var(--rep-accent); }
.dp__ring--set svg { width: 46%; height: 46%; }
.dp__ring--bat { left: calc(153 * var(--px)); width: calc(52 * var(--px)); height: calc(52 * var(--px)); border-color: var(--rep-score-good); color: var(--rep-score-good); }
.dp__ring--bat svg { width: 64%; height: 64%; }
.dp__ring--bt  { left: calc(313 * var(--px)); width: calc(52 * var(--px)); height: calc(52 * var(--px)); color: var(--rep-text-muted); }
.dp__small { font-size: calc(14 * var(--px)); line-height: calc(16 * var(--px)); color: var(--rep-text-muted); }
.dp__small--bat { left: calc(153 * var(--px)); --y: 106; }
.dp__small--bt  { left: calc(313 * var(--px)); --y: 106; }
.dp__date {
  --y: 263;
  font-size: calc(18 * var(--px));
  line-height: calc(21 * var(--px));
  color: var(--rep-text-muted);
}
.dp__trash {
  position: absolute;
  left: calc(66 * var(--px));
  top: calc(233 * var(--px));
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(4 * var(--px));
  font-size: calc(16 * var(--px));
  line-height: calc(18 * var(--px));
  color: var(--rep-score-poor);
}
.dp__trash svg { width: calc(20 * var(--px)); height: calc(20 * var(--px)); }

.dp__round {
  position: absolute;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  display: grid;
  place-items: center;
  padding: 0;
}
.dp__round svg { width: 38%; height: 38%; display: block; }
.dp__back {
  left: calc(405 * var(--px));
  top: calc(233 * var(--px));
  width: max(calc(86 * var(--px)), 44px);
  height: max(calc(86 * var(--px)), 44px);
  border: 0;
  background: var(--rep-accent);
  color: var(--rep-on-accent);
  cursor: pointer;
  transition: transform var(--rep-duration-fast) var(--rep-ease-out);
}
.dp__back:active { transform: translate(-50%, -50%) scale(.98); }
.dp__sleep {
  left: calc(233 * var(--px));
  top: calc(357 * var(--px));
  width: calc(90 * var(--px));
  height: calc(90 * var(--px));
  box-sizing: border-box;
  background: var(--rep-bg);
  border: calc(3 * var(--px)) solid var(--rep-border-strong);
  color: var(--rep-text);
}
.dp__sleep svg { width: 40%; height: 40%; }

/* ── Verlauf (verlauf_build_locked): senkrecht scrollbare Liste, 340 x 300 in
 * der Bildmitte, oben und unten 90 Luft, damit auch die erste und die letzte
 * Zeile einrasten können (Satzzeile 120, Kopfzeile 56). Native Scroll-Container
 * statt LVGL: Touch, Mausrad und Tastatur scrollen von selbst, Einrasten auf die
 * Zeilenmitte per scroll-snap, ein Wisch eine Zeile (SCROLL_ONE) per snap-stop.
 * Zeilen sind nicht tippbar. ── */
.dp__vl {
  position: absolute;
  left: calc(63 * var(--px));
  top: calc(83 * var(--px));
  width: calc(340 * var(--px));
  height: calc(300 * var(--px));
  box-sizing: border-box;
  padding: calc(90 * var(--px)) 0;
  overflow-x: clip;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
}
.dp__vl::-webkit-scrollbar { display: none; }
/* Kopfzeile: Strich oben (2 px), Datum und Satzzahl in 20, Abstand 16 bis zum Text. */
.dp__vl-day {
  box-sizing: border-box;
  height: calc(56 * var(--px));
  padding-top: calc(16 * var(--px));
  border-top: max(1px, calc(2 * var(--px))) solid var(--rep-border-strong);
  font-size: calc(20 * var(--px));
  line-height: calc(22 * var(--px));
  color: var(--rep-text-muted);
  text-align: center;
  white-space: pre;
}
/* Satzzeile (verlauf_satzzeile): Score-Ring links (52, Bogen 6), Übung 20 und
 * Uhrzeit 18 rechts davon (Spalte 78, Mitte -12 und +13), Kennzahlen 16 darunter
 * (Mitte +41, ab Spalte 14), rechts gross die Wiederholungen in 48, weiss. Ohne
 * Uhrzeit steht nur der Name, mittig in der Zeile. */
.dp__vl-row {
  position: relative;
  height: calc(120 * var(--px));
  scroll-snap-align: center;
  scroll-snap-stop: always;
}
.dp__vl-ring { position: absolute; left: calc(14 * var(--px)); top: calc(34 * var(--px)); width: calc(52 * var(--px)); height: calc(52 * var(--px)); display: grid; place-items: center; }
.dp__vl-ring svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.dp__vl-ring circle { fill: none; stroke-width: 6; }
.dp__vl-ring .t { stroke: var(--rep-border); }
.dp__vl-ring-n { position: relative; font-size: calc(22 * var(--px)); line-height: calc(25 * var(--px)); color: var(--rep-text); }
.dp__vl-ring-n--none { color: var(--rep-text-muted); }
.dp__vl-name, .dp__vl-time, .dp__vl-reps, .dp__vl-kz { position: absolute; transform: translateY(-50%); white-space: nowrap; }
.dp__vl-name {
  left: calc(78 * var(--px));
  top: calc(48 * var(--px));
  width: calc(172 * var(--px));
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: calc(20 * var(--px));
  line-height: calc(22 * var(--px));
  color: var(--rep-text);
}
.dp__vl-name--solo { top: calc(60 * var(--px)); }
.dp__vl-time {
  left: calc(78 * var(--px));
  top: calc(73 * var(--px));
  font-size: calc(18 * var(--px));
  line-height: calc(21 * var(--px));
  color: var(--rep-text-muted);
}
.dp__vl-reps {
  right: calc(14 * var(--px));
  top: calc(60 * var(--px));
  font-size: calc(48 * var(--px));
  line-height: calc(52 * var(--px));
  color: var(--rep-text);
}
.dp__vl-kz {
  left: calc(14 * var(--px));
  top: calc(101 * var(--px));
  font-size: calc(16 * var(--px));
  line-height: calc(18 * var(--px));
  color: var(--rep-text-muted);
  white-space: pre;
}
.dp__vl-empty { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); font-size: calc(24 * var(--px)); color: var(--rep-text-muted); white-space: nowrap; }
.dp__vl:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--rep-focus-ring); }
/* Rückweg-Streifen links (56 x 280) mit Pfeil. */
.dp__vl-back {
  position: absolute;
  left: 0;
  top: calc(93 * var(--px));
  width: calc(56 * var(--px));
  height: calc(280 * var(--px));
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--rep-text-muted);
  cursor: pointer;
}
.dp__vl-back svg { width: calc(26 * var(--px)); height: calc(26 * var(--px)); }

/* ── Übungswahl (uebung_build_locked): Pillenliste 340 x 300, Pillen 340 x 54,
 * Lücke 6, Vorwahl lime in der Mitte, Positionsbogen rechts. Ein Tipp wählt und
 * schliesst, ein OK gibt es nicht. ── */
.dp__ue-title { --y: 57; font-size: calc(20 * var(--px)); line-height: calc(22 * var(--px)); color: var(--rep-text); }
.dp__ue-arc { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.dp__ue-arc path { fill: none; stroke-width: 8; stroke-linecap: round; }
.dp__ue-track { stroke: var(--rep-border); }
.dp__ue-thumb { stroke: var(--rep-accent); }
.dp__ue-list {
  position: absolute;
  left: calc(63 * var(--px));
  top: calc(83 * var(--px));
  width: calc(340 * var(--px));
  height: calc(300 * var(--px));
  box-sizing: border-box;
  padding: calc(123 * var(--px)) 0;
  display: flex;
  flex-direction: column;
  gap: calc(6 * var(--px));
  overflow-x: clip;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
  touch-action: pan-y;
}
.dp__ue-list::-webkit-scrollbar { display: none; }
.dp__ue-pill {
  flex: none;
  height: calc(54 * var(--px));
  border: 0;
  border-radius: calc(27 * var(--px));
  background: var(--rep-surface-2);
  color: var(--rep-text);
  font-family: inherit;
  font-weight: 400;
  font-size: calc(24 * var(--px));
  scroll-snap-align: center;
  scroll-snap-stop: always;
  cursor: pointer;
}
.dp__ue-pill:active { background: var(--rep-border-strong); }
.dp__ue-pill.is-sel { background: var(--rep-accent); color: var(--rep-on-accent); }
.dp__ue-list:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--rep-focus-ring); }

/* ── Wdh.-Abfrage (repcheck_build_locked): Titel 20, «gezaehlt N», Kreis 108
 * (Rand lime 3) um die gewählte Zahl, Zahlenband 0 bis 50 (Zellen 86, Lücke 10),
 * Punkt unter dem gezählten Wert, «ohne Angabe», SPEICHERN 200 x 72. ── */
.dp__rc-title { --y: 65; font-size: calc(20 * var(--px)); line-height: calc(22 * var(--px)); color: var(--rep-text); }
.dp__rc-counted { --y: 113; font-size: calc(18 * var(--px)); line-height: calc(21 * var(--px)); color: var(--rep-text-muted); }
.dp__rc-circle {
  position: absolute;
  left: calc(179 * var(--px));
  top: calc(144 * var(--px));
  box-sizing: border-box;
  width: calc(108 * var(--px));
  height: calc(108 * var(--px));
  border-radius: 50%;
  background: var(--rep-surface-2);
  border: calc(3 * var(--px)) solid var(--rep-accent);
}
.dp__rc-strip {
  position: absolute;
  left: calc(40 * var(--px));
  top: calc(150 * var(--px));
  width: calc(386 * var(--px));
  height: calc(96 * var(--px));
  box-sizing: border-box;
  padding: 0 calc(150 * var(--px));
  display: flex;
  align-items: center;
  gap: calc(10 * var(--px));
  overflow-x: auto;
  overflow-y: clip;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  touch-action: pan-x;
}
.dp__rc-strip::-webkit-scrollbar { display: none; }
.dp__rc-n {
  flex: none;
  width: calc(86 * var(--px));
  text-align: center;
  font-size: calc(28 * var(--px));
  line-height: 1.15;
  color: var(--rep-text-muted);
  scroll-snap-align: center;
  scroll-snap-stop: always;
  cursor: pointer;
}
.dp__rc-n.is-sel { font-size: calc(48 * var(--px)); color: var(--rep-accent); }
.dp__rc-dot {
  position: absolute;
  top: calc(70 * var(--px));
  width: calc(8 * var(--px));
  height: calc(8 * var(--px));
  border-radius: 50%;
  background: var(--rep-accent);
}
.dp__rc-strip:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--rep-focus-ring); }
.dp__rc-skip {
  position: absolute;
  left: calc(133 * var(--px));
  top: calc(297 * var(--px));
  width: calc(200 * var(--px));
  height: max(calc(40 * var(--px)), 32px);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--rep-text-muted);
  font-family: inherit;
  font-weight: 400;
  font-size: calc(16 * var(--px));
  cursor: pointer;
}
.dp__rc-ok {
  position: absolute;
  left: calc(133 * var(--px));
  top: calc(371 * var(--px));
  width: calc(200 * var(--px));
  height: max(calc(72 * var(--px)), 44px);
  padding: 0;
  border: 0;
  border-radius: calc(36 * var(--px));
  background: var(--rep-accent);
  color: var(--rep-on-accent);
  font-family: inherit;
  font-weight: 400;
  font-size: calc(20 * var(--px));
  cursor: pointer;
}
.dp__rc-ok:active { transform: scale(.98); }

/* ── Satzende: Vollbild in der Signalfarbe des Bandes. Unter 6 Wiederholungen
 * (seit 1.9.20) grau, «-» statt «X/10» und «Score ab 6 Wdh». ── */
.dp__popup {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  padding: 0;
  border-radius: 50%;
  cursor: pointer;
  font-family: inherit;
  color: var(--rep-on-accent);
  background: var(--dp-band, var(--rep-score-top));
}
.dp__popup[hidden] { display: none; }
.dp__popup[data-band="poor"], .dp__popup[data-band="none"] { color: var(--rep-text); }
/* Score als "X/10" in 48, Band-Name in 28, wie ui_show_quality_popup. */
.dp__popup-score { --y: 215; font-size: calc(48 * var(--px)); line-height: calc(52 * var(--px)); }
.dp__popup-name  { --y: 269; font-size: calc(28 * var(--px)); line-height: calc(30 * var(--px)); }

/* Tastaturfokus wie im Rest der Seite: Innenring in der Grundfarbe, aussen Akzent. */
.dp button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--rep-bg), 0 0 0 4px var(--rep-focus-ring);
}
.dp__popup:focus-visible { box-shadow: inset 0 0 0 4px var(--rep-bg), inset 0 0 0 7px var(--rep-focus-ring); }
.dp__edge:focus-visible { box-shadow: inset 0 0 0 2px var(--rep-focus-ring); }

/* ── Bedienung unter dem Display ── */
.dp__ctl { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.dp__ctl .rep-btn { min-height: 44px; }
.dp__tag { margin: 0; }
.dp__hint { margin: 0; font-size: .8rem; color: var(--rep-text-muted); text-align: center; max-width: 360px; line-height: 1.5; } /* nur noscript */
.dp [hidden] { display: none !important; }
.dp__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

.dp__ctl .rep-btn[aria-pressed="true"] { border-color: var(--rep-accent); }

/* ── Karte «Bewegungsverlauf» (Nachbau der App-Karte, Linie in Lime statt Blau) ──
 * Mobil unter dem Display, ab 760 px links neben dem Display unter der Überschrift.
 * Daten: verlauf-demo.json, y je Satz auf volle Höhe gestreckt, nie eine Zahl an der Achse.
 * Die Kurve deckt sich in 150 ms bis zum Ende der gezählten Wiederholung auf (clip-path);
 * bei reduzierter Bewegung steht sie sofort (components.css setzt die Dauer auf null). */
.dp-grid { grid-template-columns: 1fr; grid-template-areas: "head" "dp" "card"; row-gap: 24px; }
.dp-grid__head { grid-area: head; }
.dp-grid > .dp { grid-area: dp; }
.dp-grid > .vlc { grid-area: card; }
@media (min-width: 760px) {
  .dp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-areas: "head dp" "card dp"; }
  .dp-grid__head { align-self: end; }
  .dp-grid > .vlc { align-self: start; }
}

.vlc {
  position: relative;
  box-sizing: border-box;
  width: 100%;
  max-width: 520px;
  justify-self: center;
  padding: var(--rep-space-3) var(--rep-space-3) var(--rep-space-4);
  background: var(--rep-surface);
  border: 1px solid var(--rep-border);
  border-radius: var(--rep-radius);
}
@media (min-width: 760px) { .vlc { justify-self: start; } }
@media (min-width: 400px) { .vlc { padding: var(--rep-space-4) var(--rep-space-4) var(--rep-space-4); } }
.vlc[hidden] { display: none; }
.vlc__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--rep-space-1) var(--rep-space-3); min-height: 24px; }
.vlc__title { margin: 0; font-size: .75rem; font-weight: 600; text-transform: uppercase; letter-spacing: var(--rep-tracking-eyebrow); color: var(--rep-text-muted); }
.vlc__meta { font-family: var(--rep-font-mono); font-size: 11px; color: var(--rep-text-faint); white-space: nowrap; }

/* Plotfläche: oben 30 px Reserve für die Marken, unten die Grundlinie. */
.vlc__plot { position: relative; height: 176px; margin-top: var(--rep-space-2); border-bottom: 1px solid var(--rep-border); }
.vlc__draw { position: absolute; left: 0; right: 0; top: 30px; bottom: 0; clip-path: inset(-6px calc(0% - 6px) -6px -6px); transition: clip-path .15s var(--rep-ease-out); }
.vlc__draw svg { display: block; width: 100%; height: 100%; overflow: visible; }
.vlc__band { fill: var(--rep-surface-3); }
.vlc__line { fill: none; stroke: var(--rep-accent); stroke-width: 1.6px; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; transition: opacity var(--rep-duration-base) var(--rep-ease); }
.vlc__line--sel { stroke-width: 2.4px; opacity: 0; }
.vlc.has-sel .vlc__line:not(.vlc__line--sel) { opacity: .45; }
.vlc.has-sel .vlc__line--sel { opacity: 1; }

/* Marken über den Gipfeln: --x und --f (Anteil von oben in der Zeichenfläche) setzt das Skript. */
.vlc__marks { position: absolute; inset: 0; pointer-events: none; }
.vlc__m {
  position: absolute;
  left: calc(var(--x) * 1%);
  top: max(0px, calc(30px + (100% - 30px) * var(--f) - 26px));
  box-sizing: border-box;
  width: 18px; height: 18px; margin-left: -9px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--rep-surface-2);
  border: 1px solid var(--rep-border-strong);
  color: var(--rep-text-muted);
  font-family: var(--rep-font-mono); font-size: 10px; line-height: 1;
  opacity: 0; transform: scale(.7); transform-origin: 50% 100%;
  transition: opacity .15s var(--rep-ease-out), transform .15s var(--rep-ease-out), background-color var(--rep-duration-base) var(--rep-ease);
}
.vlc__m.is-on { opacity: 1; transform: none; }
/* Ohne Nummer (Marken zu dicht): nur ein Punkt, Zahl für die Anzeige weg. */
.vlc__m:not(.is-n) { width: 6px; height: 6px; margin-left: -3px; top: max(0px, calc(30px + (100% - 30px) * var(--f) - 14px)); font-size: 0; background: var(--rep-border-strong); }
.vlc__m.is-sel { background: var(--rep-accent); border-color: var(--rep-accent); color: var(--rep-on-accent); font-weight: 700; transform: scale(1.2); }

/* Zeile der gewählten Welle: zwei Pfeile à 44 px und der Text dazwischen. */
.vlc__sel { display: flex; align-items: center; gap: var(--rep-space-2); min-height: 64px; margin-top: var(--rep-space-2); }
.vlc__arrow { flex: none; width: 44px; height: 44px; padding: 0; display: flex; align-items: center; justify-content: center; border: 0; border-radius: 50%; background: transparent; color: var(--rep-text); cursor: pointer; transition: background-color var(--rep-duration-base) var(--rep-ease), color var(--rep-duration-base) var(--rep-ease); }
.vlc__arrow svg { width: 24px; height: 24px; }
.vlc__arrow:not(:disabled):active { background: var(--rep-surface-3); }
.vlc__arrow:disabled { color: var(--rep-text-faint); cursor: default; }
.vlc__arrow:focus-visible { outline: 2px solid var(--rep-focus-ring); outline-offset: 0; }
@media (hover: hover) { .vlc__arrow:not(:disabled):hover { background: var(--rep-surface-3); } }
.vlc__txt { flex: 1; min-width: 0; margin: 0; display: flex; flex-direction: column; gap: var(--rep-space-1); text-align: center; }
.vlc__t1 { font-family: var(--rep-font-display); font-size: 16px; font-weight: 500; color: var(--rep-text); font-variant-numeric: tabular-nums; }
.vlc__t2 { font-family: var(--rep-font-mono); font-size: 12px; line-height: 1.4; color: var(--rep-text-muted); }
.vlc__note { margin: var(--rep-space-2) 0 0; font-size: 12px; line-height: 1.5; color: var(--rep-text-muted); }
.vlc__note + .vlc__note { margin-top: var(--rep-space-1); font-size: 11px; }

/* ── Display auf dem 3D-Modell (Startseite, Sektion «Probier es aus») ──
 * Nur aktiv mit .dp--modell am Wurzelelement der Vorschau, andere Vorschauen bleiben unberührt.
 * Das Bild (assets/product/nilo-modell-3d-{480,960,1440}.webp) ist ein Standbild aus den echten Onshape-Dateien
 * (Assembly_v2: Gehäuse «Part 1», Deckglas «DO0143FMST02_TP», Buchse «TYPE-C_16PIN-9X3X7_3»), gerendert mit
 * three.js ausserhalb der Website. Glas ohne Displayinhalt, transparenter Hintergrund, 2880 x 3110 px
 * Rohbild. Boden: schwach beleuchtet (Deckkraft 0.12) mit dunkler Kontaktzone am Gehäuse (fast schwarz am Rand,
 * in rund 4 mm ausgeblendet) und weicher Verdunklung bis rund 9 mm Abstand; gedacht für #0A0A0A.
 * Kamera: Azimut 215 Grad, Höhe 50 Grad (20 Grad aufrechter als zuvor, das Gerät steht mehr zum Betrachter), Perspektive aus 420 mm Abstand auf die Bildmitte, Bildfeld aus den
 * Bildgrenzen des Geräts plus Rand (4 mm seitlich, 9 mm unten, 2 mm oben). Der Parameter fov = 14 Grad und der Abstand 420 mm sind gegenüber
 * der alten Fassung unverändert, wirksam ist das Bildfeld aber viel enger, weil der Render den Sichtkegel auf die Bildgrenzen des Geräts zuschneidet:
 * 51.64 px/mm bei 2880 px Breite (Ebene des Panels, vorher 51.56), also 2 * atan(27.88 / 420) = rund 7.6 Grad horizontal und
 * 2 * atan(30.11 / 420) = rund 8.2 Grad vertikal (vorher 7.3 Grad bei 26.68 mm halber Höhe). Das Bild ist höher, weil das aufrechtere Gerät mehr Höhe braucht.
 * Das Display liegt in der Ebene des Panels (Glas-Unterseite, z = 21 mm im Gehäuse-Rahmen). Der Kreis des
 * Rahmens hat r = 18.67 mm (aktive Fläche 18.175 mm plus 0.5 mm schwarzer Rand, den .8 % Padding wieder
 * abzieht) und projiziert sich als Ellipse: Mitte (1440.0, 1004.1) px, Halbachsen 964.15 und 728.78 px,
 * b/a 0.7559 (asin = 49.1 Grad, vorher 0.4814 = 28.8 Grad, Differenz 20.3 Grad), Drehung der Hauptachse 0.13 Grad (nicht angesetzt), Abweichung vom Ellipsenmodell < 1e-5.
 * .dp__frame ist ein Quadrat mit dem Durchmesser der grossen Halbachse (2 * 964.15 / 2880 = 66.955 % der
 * Breite; left = (1440 - 964.15) / 2880 = 16.523 %; top = (1004.1 - 964.15) / 3110 = 1.285 % der Höhe) und
 * liegt per scale(1, b/a) genau darauf. Bild und Display stehen in Prozent desselben Kastens mit fester
 * Seitenrelation (2880 : 3110), sie skalieren also gemeinsam. Weil
 * .dp__screen die Containergrösse und damit --px aus der Layout-Breite nimmt (nicht aus der
 * transformierten), bleiben alle Geräteeinheiten gültig; Tippen und Wischen laufen durch die
 * Transformation (Hit-Test im Browser, px() in device-preview.js misst die Layout-Breite,
 * die horizontale Skalierung ist 1). */
.dp--modell { --dm-w: 340px; --dm-sy: 0.7559; }
@media (min-width: 760px) { .dp--modell { --dm-w: 480px; } }
.dm {
  position: relative;
  width: min(100%, var(--dm-w));
  aspect-ratio: 2880 / 3110;
  overflow: clip;
}
.dm__img {
  position: absolute;
  width: 100%;
  left: 0;
  top: 0;
  height: auto;
  max-width: none;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}
.dp--modell .dp__frame {
  --dm-inset: 1;
  position: absolute;
  left: 16.523%;
  top: 1.285%;
  width: 66.955%;
  /* Display einen Hauch hinter der Glaskante: schwarzer Rand (AMOLED unter Glas, 0,8 % der
   * Kastenbreite), damit der Rahmen des Geräts das Display sichtbar umschliesst. */
  padding: .8%;
  border: 0;
  background: #020202;
  box-shadow: none;
  transform-origin: 50% 50%;
  transform: scale(var(--dm-inset), calc(var(--dm-inset) * var(--dm-sy)));
  /* weiche Aussenkante, Display und Render verschmelzen (kein hartes Ausschneiden) */
  -webkit-mask-image: radial-gradient(circle, #000 97.6%, transparent 100%);
  mask-image: radial-gradient(circle, #000 97.6%, transparent 100%);
}
/* Auf dem Modell leuchtet nichts so grell wie in der Reinzeichnung: leicht gedämpft.
 * Kontrast bleibt hoch (weiss auf Schwarz, dunkle Tinte auf Lime). */
.dp--modell .dp__screen { filter: brightness(.9) saturate(.92); }
/* Satzende-Vollbild: Lime als leuchtende Fläche mit Tiefe statt als flacher Aufkleber,
 * Mitte etwas heller, zum Rand hin dunkler. */
.dp--modell .dp__popup {
  background-image:
    radial-gradient(circle at 50% 46%, rgb(255 255 255 / .14) 0, transparent 48%),
    radial-gradient(circle at 50% 50%, transparent 58%, rgb(0 0 0 / .26) 100%);
}
/* Glas: Randabdunklung (Innenrand), weicher Lichtfleck oben links und ein breiter,
 * diffuser Reflexstreifen mit schmalem Zweitstreifen. Reine Zierde, fängt keine Eingaben ab. */
.dp--modell .dp__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  background:
    linear-gradient(112deg, transparent 17%, rgb(255 255 255 / .05) 25%, rgb(255 255 255 / .11) 31%, rgb(255 255 255 / .03) 38%, transparent 40%, transparent 42%, rgb(255 255 255 / .05) 44%, transparent 47%),
    radial-gradient(ellipse at 24% 13%, rgb(255 255 255 / .12) 0, transparent 38%),
    radial-gradient(circle at 50% 50%, transparent 72%, rgb(0 0 0 / .30) 90%, rgb(0 0 0 / .62) 100%);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / .07), inset 0 0 8px rgb(0 0 0 / .55);
}

/* Trefferflächen: Das Display ist hier um b/a gestaucht (--dm-sy), eine Knopfhöhe von 70 Geräte-Pixeln
 * wird am Handy zu rund 25 CSS-px. Jeder Knopf bekommt deshalb unsichtbar mindestens 44 CSS-px Höhe
 * (--dm-hit ist diese Höhe vor der Stauchung), die Optik bleibt unverändert. Das Pseudoelement gehört zum
 * Knopf, ein Tipp darauf löst dessen Klick aus. Die Fläche endet am runden Rand des Displays (overflow: clip). */
.dp--modell { --dm-hit: calc(44px / var(--dm-sy)); }
.dp--modell .dp__go::before,
.dp--modell .dp__pill::before,
.dp--modell .dp__back::before,
.dp--modell .dp__vl-back::before,
.dp--modell .dp__rc-ok::before,
.dp--modell .dp__rc-skip::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: min(0px, calc((100% - var(--dm-hit)) / 2));
  bottom: min(0px, calc((100% - var(--dm-hit)) / 2));
}
/* Wdh.-Abfrage: Auf dem gestauchten Display (mobil rund 172 CSS-px hoch) bleiben unter dem Zahlenband nur
 * rund 80 CSS-px Höhe, zwei übereinander stehende Knöpfe mit je 44 CSS-px passen nicht. Deshalb stehen
 * «ohne Angabe» (links) und SPEICHERN (rechts) hier nebeneinander (je 148 Geräte-px breit, mobil rund 71 CSS-px,
 * die Zeile liegt bei y 316..388 und damit ganz im Kreis). Ihre unsichtbare Trefferfläche reicht vom Zahlenband
 * (y 246) bis zum Rand des Displays, am Handy sind das über 44 CSS-px senkrecht durch die Knopfmitte.
 * Die Knöpfe im Gerät selbst stehen übereinander (rep12_ui.cpp), das Modell ordnet nur um. */
.dp--modell .dp__rc-skip,
.dp--modell .dp__rc-ok {
  top: calc(316 * var(--px));
  width: calc(148 * var(--px));
  height: calc(72 * var(--px));
}
.dp--modell .dp__rc-skip { left: calc(80 * var(--px)); }
.dp--modell .dp__rc-ok { left: calc(238 * var(--px)); }
.dp--modell .dp__rc-skip::before,
.dp--modell .dp__rc-ok::before {
  top: calc(-70 * var(--px));
  bottom: calc(-90 * var(--px));
}
.dp--modell .dp__rc-skip::before { left: calc(-12 * var(--px)); right: calc(-5 * var(--px)); }
.dp--modell .dp__rc-ok::before { left: calc(-5 * var(--px)); right: calc(-12 * var(--px)); }
/* Übung-Auswahl: unten begrenzt der Kreisrand die Fläche der Pille, nach oben bleibt bis zur Fläche von START
 * Platz. Sie reicht deshalb zusätzlich 14 Geräte-px nach oben und bleibt auch bei 360 CSS-px Breite über 44 CSS-px hoch. */
.dp--modell .dp__pill::before {
  top: calc(min(0px, (100% - var(--dm-hit)) / 2) - 14 * var(--px));
}
/* Randzonen links (Menü) und rechts (Verlauf): mobil sind 70 Geräte-px plus 16 Zusatz nur rund 41 CSS-px breit.
 * Die Zusatzfläche reicht deshalb nach innen genau so weit, dass die Zone ab dem Displayrand mindestens 44 CSS-px breit ist
 * (am Desktop gilt weiter die alte Breite). Die Höhe (320 Geräte-px, mobil rund 90 CSS-px) bleibt. */
.dp--modell .dp__edge--l::after { right: calc(-1 * max(16 * var(--px), 44px - 70 * var(--px))); }
.dp--modell .dp__edge--r::after { left: calc(-1 * max(16 * var(--px), 44px - 70 * var(--px))); }
/* Übungsliste: Die Zeilen stehen im Takt 60 Geräte-px (JS: UE_TAKT), mobil sind das rund 21 CSS-px. 44 CSS-px sind bei
 * diesem Takt nicht möglich, ohne die Liste umzubauen. Die Trefferfläche füllt wenigstens die 6 Geräte-px Lücke zwischen den Zeilen. */
.dp--modell .dp__ue-pill { position: relative; }
.dp--modell .dp__ue-pill::before { content: ""; position: absolute; left: 0; right: 0; top: calc(-3 * var(--px)); bottom: calc(-3 * var(--px)); }
/* Rückweg-Streifen im Verlauf: auch in der Breite mindestens 44 CSS-px. */
.dp--modell .dp__vl-back::before {
  right: calc(-1 * max(0px, 44px - 100%));
}
/* START/STOPP: die Fläche reicht nach oben bis zum Rand des Displays (dort endet die Kreisfläche ohnehin),
 * den Rest nimmt sie nach unten, damit es auch im oberen Kreisabschnitt volle 44 CSS-px sind. */
.dp--modell .dp__go::before {
  top: calc(-52 * var(--px));
  bottom: min(0px, calc(100% + 52 * var(--px) - var(--dm-hit)));
}
