/* =========================================================
   Life Archive – Reader
   Bibliothek · Lesebildschirm · Stats · Annotations

   Aufgebaut wie die anderen Bereiche: .mnt-card als Container,
   .pop für Popups – beide aus styles/components.css –, Akzentfarbe
   aus der Modul-Registry. Neu ist nur, was es vorher nicht gab –
   Cover-Raster, Lesefläche, Markierungen.
   ========================================================= */

.rdr {
  --accent-app:  var(--c-reader);
  --accent-deep: var(--c-reader-stroke);
  --rd-line: rgba(var(--o), .08);
}

/* =========================================================
   Gemeinsame Knöpfe und Felder
   ========================================================= */

.rd-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 20px;
  border-radius: 8px;
  background: var(--accent-app);
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
  transition: filter var(--dur) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.rd-btn:hover { filter: brightness(1.08); }
.rd-btn:active { transform: scale(.96); }

.rd-btn--ghost {
  background: transparent;
  border: 1px solid var(--accent-app);
  color: var(--accent-app);
  font-weight: 500;
}

.rd-btn--ghost.is-on { background: var(--accent-app); color: var(--ink); }
.rd-btn--wide { width: 100%; margin-top: 16px; }

/* Löschen sieht aus wie Löschen. Kein Rot auf Rot: die Schrift ist
   dunkel genug für den Kontrast, den ein Knopf braucht. */
.rd-btn--danger { background: #d98a8a; color: #2a1414; }

.rd-btn[disabled] {
  opacity: .4;
  cursor: default;
  pointer-events: none;
}

.rd-mini {
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  font-size: 12px;
  color: var(--text-dim);
  transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}

.rd-mini:hover { border-color: var(--accent-app); color: var(--accent-app); }

.rd-iconbtn {
  position: relative;
  width: 40px;
  height: 40px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--rd-line);
  transition: background-color var(--dur) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.rd-iconbtn img { width: 19px; }
.rd-iconbtn:hover { background: var(--surface-2); }
.rd-iconbtn:active { transform: scale(.92); }
.rd-iconbtn.is-on { border-color: var(--accent-app); }

.rd-iconbtn__dot {
  position: absolute;
  top: 6px;
  inset-inline-end: 6px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent-app);
}

.rd-input {
  width: 100%;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--g-47);
  border: 1px solid rgba(var(--o), .10);
  color: var(--text);
  font: inherit;
  font-size: 16px;
  outline: none;
}

.rd-input:focus { border-color: var(--accent-app); }
.rd-input--area { resize: vertical; line-height: 1.5; }

.rd-empty {
  padding: 14px 2px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-dim);
}

.rd-warn {
  margin-bottom: 12px;
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid rgba(var(--t-fitness-stroke), .45);
  background: rgba(var(--t-fitness-stroke), .10);
  font-size: 13px;
  color: #ff9a9a;
}

/* Segmentierte Auswahl (Ausrichtung, Zeitraum, Art) */

.rd-seg {
  display: flex;
  gap: 6px;
  padding: 4px;
  border-radius: 10px;
  background: var(--g-47);
}

.rd-seg__btn {
  flex: 1;
  padding: 8px 6px;
  border-radius: 7px;
  font-size: 13px;
  color: var(--text-dim);
  transition: background-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}

.rd-seg__btn.is-on { background: var(--accent-app); color: var(--ink); font-weight: 600; }
.rd-seg--sm .rd-seg__btn { padding: 6px 4px; font-size: 12px; }

/* =========================================================
   Bibliothek

   Eine Zeile Suche, eine Zeile Ordner, darunter Cover. Alles
   andere liegt in Blättern, die von unten kommen.
   ========================================================= */

.rd-lib { padding-top: 2px; }

.lib-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.lib-search {
  position: relative;
  flex: 1;
  min-width: 0;
}

/* Die Lupe ist gezeichnet statt geladen: ein Kreis und ein Strich –
   dafür lohnt keine eigene Datei. */
.lib-search__icon {
  position: absolute;
  inset-inline-start: 12px;
  top: 50%;
  width: 10px;
  height: 10px;
  margin-top: -6px;
  border: 1.6px solid var(--text-faint);
  border-radius: 50%;
  pointer-events: none;
}

.lib-search__icon::after {
  content: "";
  position: absolute;
  inset-inline-end: -4px;
  bottom: -3px;
  width: 6px;
  height: 1.6px;
  background: var(--text-faint);
  transform: rotate(45deg);
}

.lib-search input {
  width: 100%;
  height: 38px;
  padding: 0 12px 0 32px;
  border-radius: 11px;
  background: var(--surface);
  border: 1px solid transparent;
  color: var(--text);
  font: inherit;
  font-size: 16px;
  outline: none;
}

.lib-search input::placeholder { color: var(--text-faint); }
.lib-search input:focus { border-color: var(--accent-deep); background: var(--surface-2); }
.lib-search input::-webkit-search-cancel-button { filter: invert(1); opacity: .5; }

.lib-round {
  width: 38px;
  height: 38px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 11px;
  background: var(--surface);
  transition: background-color var(--dur) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

.lib-round img { width: 18px; }
.lib-round:hover { background: var(--surface-2); }
.lib-round:active { transform: scale(.92); }
.lib-round.is-on { background: rgba(var(--t-reader), .22); }

.lib-round--accent { background: var(--accent-app); }
.lib-round--accent img { width: 20px; filter: none; }
.lib-round--accent:hover { background: var(--accent-app); filter: brightness(1.08); }

/* Kopfzeile eines geöffneten Ordners */

.lib-crumb {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

.lib-crumb__title {
  flex: 1;
  min-width: 0;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lib-crumb__count {
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--surface-2);
  font-size: max(var(--fs-floor), 11.5px);
  color: var(--text-dim);
}

/* Ordner-Kachel: die ersten vier Cover darin, wie auf einem
   Startbildschirm. Ist ein fünftes da, sagt der letzte Platz das,
   statt so zu tun, als wäre der Ordner zu Ende. */
.lib-folder {
  display: grid;
  place-items: center;
  padding: 8px;
  background: var(--surface);
  border: 1px solid var(--rd-line);
  box-shadow: none;
}

.lib-folder__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 6px;
  width: 100%;
  height: 100%;
}

.lib-folder__mini {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 4px;
  background: var(--surface-2);
}

.lib-folder__empty {
  border-radius: 4px;
  background: rgba(var(--o), .04);
}

.lib-folder__more {
  display: grid;
  place-items: center;
  border-radius: 4px;
  background: rgba(var(--t-reader), .18);
  font-size: 13px;
  font-weight: 600;
  color: var(--accent-app);
}

.lib-tile__caption {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 5px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--text-dim);
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lib-tile__caption i { font-style: normal; font-size: max(var(--fs-floor), 10.5px); color: var(--text-faint); }

/* Regal */

.lib-shelf { margin-bottom: 22px; }

.lib-shelf__head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.lib-shelf__title {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
}

.lib-shelf__count {
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  font-size: max(var(--fs-floor), 11px);
  color: var(--text-dim);
}

.lib-shelf__more {
  width: 28px;
  height: 28px;
  margin-inline-start: auto;
  border-radius: 8px;
  position: relative;
}

.lib-shelf__more::before {
  content: "";
  position: absolute;
  inset-inline-start: 50%;
  top: 50%;
  width: 3px;
  height: 3px;
  margin: -1.5px 0 0 -1.5px;
  border-radius: 50%;
  background: var(--text-dim);
  box-shadow: -6px 0 0 var(--text-dim), 6px 0 0 var(--text-dim);
}

.lib-shelf__more:hover { background: var(--surface-2); }

.lib-next {
  display: block;
  width: 100%;
  margin-bottom: 10px;
  padding: 8px 12px;
  border-radius: 9px;
  background: rgba(var(--t-reader), .12);
  font-size: 12.5px;
  color: var(--accent-app);
  text-align: start;
}

.lib-next:hover { background: rgba(var(--t-reader), .2); }

/* Reihen laufen waagerecht, Einzelbände stehen im Raster. */
.lib-strip {
  display: flex;
  gap: 12px;
  margin: 0 calc(var(--gutter) * -1);
  padding: 2px var(--gutter) 6px;
  overflow-x: auto;
  scrollbar-width: none;
}

.lib-strip::-webkit-scrollbar { display: none; }
.lib-strip .lib-tile { flex: none; width: 104px; }

.lib-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(98px, 1fr));
  gap: 14px 12px;
}

.lib-tile { position: relative; }

.lib-tile__open {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 2 / 3;
  overflow: hidden;
  border-radius: 10px;
  background: var(--surface-2);
  box-shadow: 0 6px 18px rgba(var(--o-deep), .38);
  transition: transform var(--dur) var(--ease-out);
}

.lib-tile__open:hover { transform: translateY(-3px); }
.lib-tile__open:active { transform: scale(.97); }

.lib-tile__cover { width: 100%; height: 100%; object-fit: cover; }

.lib-tile__shade {
  position: absolute;
  inset: auto 0 0 0;
  height: 46%;
  background: linear-gradient(to top, rgba(var(--o-deep), .8), transparent);
  pointer-events: none;
}

.lib-tile__badge {
  position: absolute;
  inset-inline-start: 6px;
  bottom: 8px;
  padding: 2px 7px;
  border-radius: 6px;
  background: rgba(var(--o-deep), .5);
  backdrop-filter: blur(4px);
  font-size: max(var(--fs-floor), 10px);
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--g-01);
}

.lib-tile__badge.is-read { background: var(--accent-app); color: var(--ink); }
.lib-tile__badge.is-unread { font-weight: 500; color: rgba(var(--o), .78); }

.lib-tile__bar {
  position: absolute;
  inset-inline-start: 0;
  inset-inline-end: 0;
  bottom: 0;
  height: 2.5px;
  background: rgba(var(--o), .16);
}

.lib-tile__bar span { display: block; height: 100%; background: var(--accent-app); }

.lib-tile__menu {
  position: absolute;
  top: 5px;
  inset-inline-end: 5px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: rgba(var(--o-bg), .5);
  backdrop-filter: blur(6px);
  opacity: .85;
  transition: opacity var(--dur) var(--ease-out), background-color var(--dur) var(--ease-out);
}

.lib-tile__menu span {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--g-01);
  box-shadow: -5px 0 0 var(--g-01), 5px 0 0 var(--g-01);
}

.lib-tile__menu:hover { opacity: 1; background: rgba(var(--o-bg), .8); }

/* =========================================================
   Blätter von unten
   ========================================================= */

.rd-layer--sheet { align-items: end; padding: 0; }

.rd-pop--sheet {
  width: min(460px, 100%);
  max-height: 86dvh;
  margin-bottom: 0;
  border: 0;
  border-top: 1px solid var(--rd-line);
  border-radius: 20px 20px 0 0;
  background: var(--surface);
  animation: lib-sheet-up 300ms var(--ease-out) both;
}

@keyframes lib-sheet-up {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}

.lib-sheet {
  display: grid;
  gap: 12px;
  padding: 10px 16px calc(20px + var(--safe-bottom));
}

.lib-sheet__grip {
  width: 38px;
  height: 4px;
  margin: 0 auto 2px;
  border-radius: 999px;
  background: var(--line-strong);
}

.lib-sheet__title {
  font-size: 16px;
  font-weight: 600;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lib-sheet__rows {
  display: grid;
  border-radius: 14px;
  background: var(--g-47);
  overflow: hidden;
  max-height: 56dvh;
  overflow-y: auto;
  scrollbar-width: thin;
}

.lib-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border-bottom: 1px solid rgba(var(--o), .05);
  text-align: start;
  transition: background-color var(--dur-fast) var(--ease-out);
}

.lib-row:last-child { border-bottom: 0; }
.lib-row:active { background: rgba(var(--o), .06); }

.lib-row__icon {
  width: 20px;
  height: 20px;
  flex: none;
  background: var(--accent-app);
  -webkit-mask: var(--m) center / contain no-repeat;
          mask: var(--m) center / contain no-repeat;
}

.lib-row__icon.is-empty { background: none; }

.lib-row__body { flex: 1; min-width: 0; display: grid; gap: 1px; }

.lib-row__label {
  font-size: 15px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lib-row__hint {
  font-size: max(var(--fs-floor), 11.5px);
  color: var(--text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lib-row__mark {
  width: 16px;
  height: 9px;
  flex: none;
  border-inline-start: 2px solid var(--accent-app);
  border-bottom: 2px solid var(--accent-app);
  transform: rotate(-45deg) translate(1px, -3px);
}

.lib-row.is-danger .lib-row__label { color: #ff9a9a; }
.lib-row.is-danger .lib-row__icon { background: #ff9a9a; }

.lib-sheet__cancel {
  padding: 13px;
  border-radius: 14px;
  background: var(--g-47);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-dim);
}

.lib-sheet__cancel:active { background: rgba(var(--o), .06); }

.lib-sheet__acts { display: flex; gap: 10px; }
.lib-sheet__acts .rd-btn { flex: 1; }

/* ---------- Fenster "Information" -------------------------------------------
   Dieselbe Sprache wie die übrigen Blätter von unten: Griff, Titel,
   Flächen in --field-bg, Knöpfe unten. Nur steht hier nichts zum
   Antippen, sondern etwas zum Lesen – deshalb keine Zeilen, sondern
   Zahlen und eine Tabelle. */

.rd-info { max-height: 82dvh; overflow-y: auto; scrollbar-width: thin; }

/* Vier Zahlen, zwei mal zwei – die Fragen, die man zuerst stellt. */
.rd-info__stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  border-radius: 14px;
  background: var(--line-strong);
  overflow: hidden;
}

.rd-info__stat {
  display: grid;
  gap: 2px;
  padding: 12px 14px;
  background: var(--g-47);
}

.rd-info__value {
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 600;
  color: var(--accent-app);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rd-info__label {
  font-size: max(var(--fs-floor), 11.5px);
  color: var(--text-faint);
}

.rd-info__jump { width: 100%; }

.rd-info__desc {
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--g-47);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--text-dim);
}

.rd-info__meta {
  display: grid;
  margin: 0;
  border-radius: 14px;
  background: var(--g-47);
  overflow: hidden;
}

.rd-info__row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 9px 14px;
  border-bottom: 1px solid rgba(var(--o), .05);
}

.rd-info__row:last-child { border-bottom: 0; }

.rd-info__row dt {
  flex: none;
  width: 96px;
  font-size: max(var(--fs-floor), 11.5px);
  color: var(--text-faint);
}

/* Ein Klappentext bricht um, ein Verlagsname auch – hier wird nichts
   abgeschnitten, was jemand lesen wollte. */
.rd-info__row dd {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 13.5px;
  overflow-wrap: anywhere;
}

.rd-join { display: flex; gap: 4px; }

.rd-join__btn {
  padding: 4px 10px;
  border-radius: 6px;
  border: 1px solid var(--line-strong);
  font-size: max(var(--fs-floor), 11px);
  color: var(--text-dim);
}

.rd-join__btn.is-on {
  background: var(--accent-app);
  border-color: transparent;
  color: var(--ink);
  font-weight: 600;
}

.rd-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }

.rd-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  font-size: 12.5px;
  color: var(--text-dim);
  transition: all var(--dur) var(--ease-out);
}

.rd-chip span { font-size: max(var(--fs-floor), 10.5px); opacity: .7; }
.rd-chip.is-on { background: var(--accent-app); border-color: transparent; color: var(--ink); }

/* Raster */

.rd-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 14px;
}

.rd-tile { position: relative; }

.rd-tile__open {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 2 / 3;
  overflow: hidden;
  border-radius: 8px;
  background: var(--surface-2);
  box-shadow: var(--shadow-1);
  transition: transform var(--dur) var(--ease-out);
}

.rd-tile__open:hover { transform: translateY(-3px); }
.rd-tile__open:active { transform: scale(.97); }

.rd-tile__cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Der Verlauf unten macht Prozentzahl und Status lesbar, egal wie
   hell das Cover ist. */
.rd-tile__shade {
  position: absolute;
  inset: auto 0 0 0;
  height: 52%;
  background: linear-gradient(to top, rgba(var(--o-deep), .82), transparent);
  pointer-events: none;
}

.rd-tile__bar {
  position: absolute;
  inset-inline-start: 0;
  inset-inline-end: 0;
  bottom: 0;
  height: 3px;
  background: rgba(var(--o), .18);
}

.rd-tile__bar span {
  display: block;
  height: 100%;
  background: var(--accent-app);
}

.rd-tile__badge {
  position: absolute;
  inset-inline-end: 6px;
  bottom: 8px;
  padding: 2px 7px;
  border-radius: 5px;
  background: rgba(var(--o-deep), .55);
  font-size: max(var(--fs-floor), 10.5px);
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--g-01);
}

.rd-tile__badge.is-read { background: var(--accent-app); color: var(--ink); }
.rd-tile__badge.is-unread { background: rgba(var(--o-deep), .55); color: var(--text-dim); font-weight: 500; }

.rd-tile__menu {
  position: absolute;
  top: 4px;
  inset-inline-end: 4px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  background: rgba(var(--o-bg), .62);
  backdrop-filter: blur(3px);
  transition: background-color var(--dur) var(--ease-out);
}

.rd-tile__menu img { width: 15px; }
.rd-tile__menu:hover { background: rgba(var(--o-bg), .9); }

/* Serien */

.rd-series {
  margin-bottom: 22px;
  padding: 12px 12px 14px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--rd-line);
  border-top: 1.5px solid var(--accent-app);
}

.rd-series__head {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 12px;
}

.rd-series__icon { width: 20px; opacity: .85; }

.rd-series__name {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  font-weight: 500;
  color: var(--g-04);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rd-series__count { font-size: 12px; color: var(--text-faint); }

.rd-series__next {
  display: block;
  width: 100%;
  margin-top: 12px;
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px dashed var(--accent-deep);
  font-size: 13px;
  color: var(--accent-app);
  text-align: start;
}

.rd-series__next:hover { background: rgba(var(--t-reader), .12); }

.rd-shelf { margin-bottom: 20px; }

.rd-shelf__title {
  margin-bottom: 10px;
  font-size: max(var(--fs-floor), 11px);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* Leeres Regal */

.rd-blank {
  display: grid;
  justify-items: center;
  gap: 12px;
  padding: 42px 20px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
  text-align: center;
}

.rd-blank__icon { width: 54px; opacity: .5; }
.rd-blank__title { font-size: 20px; font-weight: 500; }

.rd-blank__text {
  max-width: 38ch;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-dim);
}

.rd-blank__acts { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }

/* =========================================================
   Import- und Detail-Popup
   ========================================================= */

.rd-pop { width: min(460px, 100%); }
.rd-form { display: grid; gap: 14px; }

.rd-form__top { display: flex; gap: 14px; align-items: flex-start; }

.rd-form__cover {
  width: 88px;
  aspect-ratio: 2 / 3;
  flex: none;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 6px;
  background: var(--g-47);
  border: 1px solid var(--rd-line);
}

.rd-form__cover img { width: 100%; height: 100%; object-fit: cover; }
.rd-form__cover.has-cover .rd-form__coverhint { display: none; }
.rd-form__coverhint { font-size: max(var(--fs-floor), 11px); color: var(--text-faint); }

.rd-form__meta { min-width: 0; display: grid; gap: 6px; justify-items: start; }

.rd-form__file {
  font-size: 12.5px;
  color: var(--g-16);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.rd-form__facts { font-size: max(var(--fs-floor), 11.5px); color: var(--text-faint); }

.rd-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.rd-field { display: grid; gap: 5px; }

.rd-field__label {
  font-size: max(var(--fs-floor), 11px);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.rd-form__actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 6px;
}

/* Viele Bücher auf einmal. Neben dem einen großen Knopf stehen die
   Wege für viele klein – wer zum ersten Mal kommt, sieht EINEN
   nächsten Schritt, wer eine Sammlung hat, findet seinen trotzdem. */

.rd-blank__acts { align-items: center; }
.rd-blank__more { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.rd-blank__more .rd-mini { min-height: 32px; }

.rd-bulk { display: grid; gap: 10px; }

.rd-bulk__count {
  font-size: 14px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.rd-bulk__count strong {
  margin-inline-end: 2px;
  font-size: 28px;
  font-weight: 600;
  color: var(--text);
}

/* Der Strich wächst über transform, nicht über width – kein Umbruch
   je Buch, nur ein neues Bild. */
.rd-bulk__track { height: 6px; overflow: hidden; background: rgba(var(--o), .08); }

.rd-bulk__fill {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--accent-app);
  transform: scaleX(var(--p, 0));
  transform-origin: left center;
  transition: transform var(--dur) var(--ease-out);
}

.rd-bulk__now {
  min-height: 1.4em;
  overflow: hidden;
  font-size: 13px;
  color: var(--text-dim);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rd-bulk__failed {
  display: grid;
  gap: 6px;
  max-height: 40dvh;
  margin: 4px 0 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}

.rd-bulk__failed li {
  padding: 8px 10px;
  background: var(--g-47);
  font-size: 13px;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}

@media (prefers-reduced-motion: reduce) {
  .rd-bulk__fill { transition: none; }
}

.rd-wait { display: flex; align-items: center; gap: 10px; font-size: 14px; }

.rd-wait__spin {
  width: 18px;
  height: 18px;
  flex: none;
  border-radius: 50%;
  border: 2px solid rgba(var(--o), .18);
  border-top-color: var(--accent-app);
  animation: rd-spin 800ms linear infinite;
}

@keyframes rd-spin { to { transform: rotate(360deg); } }

/* =========================================================
   Lesebildschirm
   ========================================================= */

/* The page always gets the whole screen; its height comes from
   fitPage() in read.js. Header, tools and progress line are laid over
   it instead of taking space from it – switching them on and off must
   not reflow a single line, or the page you were reading would move
   under your eyes. */
.rd-read {
  position: relative;
  min-height: 320px;
}

/* Solange gelesen wird, rückt die Seite nicht mehr für die Leisten
   ein – sie liegen darüber. */
body.is-reader .app {
  padding-top: calc(var(--safe-top) + 6px);
  padding-bottom: calc(var(--safe-bottom) + 8px);
}

/* Der Lesebildschirm selbst scrollt nie. Er passt genau, und was sich
   bewegt, ist die Seite im Buch – nicht die Seite der App. Ohne das
   genügt ein Pixel Überhang, und eine Wischbewegung nach unten zieht
   im Blättermodus die ganze Ansicht mit. */
body.is-reader { overflow: hidden; }

/* Im Blättermodus gibt es nichts zu scrollen: senkrechte Gesten
   gehören dem Markieren, waagerechte dem Blättern. */
.rd-read:not([data-reading="scroll"]) .rd-stagewrap { touch-action: pan-x; }
[data-reading="scroll"] .rd-stagewrap { touch-action: pan-y; }

/* ---------- The overlay --------------------------------------------------- */

.rd-head,
.rd-tools,
.rd-foot {
  position: absolute;
  inset-inline-start: 0;
  inset-inline-end: 0;
  z-index: 6;
  transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out);
}

/* Die Leisten der App sind fest und liegen über der Seite. Das Overlay
   des Buches muss darunter beziehungsweise darüber Platz nehmen –
   sonst steht die Fortschrittszeile hinter der Reiterleiste und die
   Kopfzeile hinter der Bereichsleiste. Genau das war passiert. */
.rd-head { top: calc(var(--sh-top-h) - var(--safe-top) - 2px); }
.rd-tools { top: calc(var(--sh-top-h) - var(--safe-top) + 50px); }

/* Die Fortschrittszeile setzt sich direkt über die Leiste – über das,
   was die Leiste wirklich verdeckt (--sh-tabs-clear), nicht über ihre
   geometrische Höhe. Mit --sh-tabs-h gerechnet stand sie um den
   Aufstieg des Sechsecks zu hoch und schwebte sichtbar im Nichts.

   Und weil sie im Lesebildschirm sitzt und der schon ein Stück über
   dem unteren Fensterrand endet, wird dieser Abstand wieder
   abgezogen: --rd-hostgap meldet ihn aus fitPage (app/reader/read.js).
   Ohne das zählte er ein zweites Mal mit. */
.rd-read { --rd-foot-b: max(0px, calc(var(--sh-tabs-clear) + 6px - var(--rd-hostgap, 8px))); }

.rd-foot { bottom: var(--rd-foot-b); }

/* Die Fortschrittszeile ist zum Lesen da, nicht zum Drücken. Ohne das
   fängt sie den Tipp ab, der unten blättern soll – und beim PDF auch
   den Knopf darunter. */
.rd-foot { pointer-events: none; }

/* Ohne Overlay sind die App-Leisten weg, dann darf die Zeile nach
   unten rücken – die Seite selbst bleibt unverändert. */
.rd-read.is-bare { --rd-foot-b: max(0px, calc(var(--safe-bottom) + 6px - var(--rd-hostgap, 8px))); }

/* Ein Hauch Fläche darunter, damit die Schrift auf dem Text lesbar
   bleibt – ohne ihn zu verdecken wie ein Vorhang. */
.rd-head,
.rd-foot {
  padding: 6px 10px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* Beim Messen der Leseposition fragt der Reader den Browser, welcher
   Buchstabe oben links steht (offsetAtPage in read.js). Geantwortet
   wird mit dem, was obenauf liegt – also mit der Kopfzeile, solange
   sie zu sehen ist. Für den Augenblick der Messung ist das Overlay
   deshalb durchlässig. */
.rd-read.is-measuring .rd-head,
.rd-read.is-measuring .rd-tools,
.rd-read.is-measuring .rd-foot { pointer-events: none; }

.rd-read.is-bare .rd-head,
.rd-read.is-bare .rd-tools {
  opacity: 0;
  pointer-events: none;
  transform: translateY(-8px);
}

/* Die Fortschrittszeile bleibt – mit ihrer Fläche. Ohne sie stand die
   Schrift direkt auf dem Text des Buches und war nicht zu lesen. */
.rd-read.is-bare .rd-foot {
  background: color-mix(in srgb, var(--bg) 94%, transparent);
}

/* Für Browser ohne color-mix: eine feste Fläche, damit die Zeile in
   jedem Fall lesbar bleibt. */
@supports not (background: color-mix(in srgb, #000 50%, transparent)) {
  .rd-head,
  .rd-foot { background: var(--g-44); }
  .rd-tool { background: #2b2016; }
}

/* Unsichtbar heißt auch: nicht im Weg. Die Leisten setzen für ihre
   gefüllten Teile selbst pointer-events, deshalb muss es hier für die
   Kinder mit gesagt werden – sonst fängt eine Leiste, die niemand
   sieht, die Berührungen des Buches ab. */
body.is-reading .sh-top,
body.is-reading .sh-tabs {
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms var(--ease-out);
}

body.is-reading .sh-top *,
body.is-reading .sh-tabs * { pointer-events: none; }


/* Peek mode – reading without moving the bookmark. The eye is drawn,
   not loaded: a circle inside an almond shape. */
.rd-peek__mark {
  position: relative;
  width: 20px;
  height: 13px;
  border: 2px solid var(--text-dim);
  border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
}

.rd-peek__mark::after {
  content: "";
  position: absolute;
  inset-inline-start: 50%;
  top: 50%;
  width: 5px;
  height: 5px;
  margin: -3.5px 0 0 -3.5px;
  border: 2px solid var(--text-dim);
  border-radius: 50%;
}

[data-peek].is-on { background: rgba(var(--t-reader), .22); border-color: var(--accent-deep); }
[data-peek].is-on .rd-peek__mark,
[data-peek].is-on .rd-peek__mark::after { border-color: var(--accent-app); }

/* Im Peek-Modus sagt die Fortschrittszeile, dass sie gerade nichts
   festhält – sonst wundert man sich, warum der Stand stehen bleibt. */
.rd-read.is-peek .rd-foot__bar span { opacity: .4; }

/* "Keine Markierungen": ein Textmarker mit einem Strich durch.
   Gezeichnet statt geladen – ein Symbol für einen Zustand, den es
   sonst nirgends im Projekt gibt, wäre eine Datei für einen
   einzigen Knopf. */
.rd-noannot__mark {
  position: relative;
  width: 18px;
  height: 13px;
}

.rd-noannot__mark::before {
  content: "";
  position: absolute;
  inset-inline-start: 1px;
  top: 2px;
  inset-inline-end: 1px;
  height: 7px;
  border-radius: 2px;
  background: var(--text-dim);
  opacity: .55;
}

/* Der Strich. Zwei Pixel höher als das Kästchen, damit er an beiden
   Ecken übersteht und als Verneinung lesbar bleibt. */
.rd-noannot__mark::after {
  content: "";
  position: absolute;
  inset-inline-start: 50%;
  top: -2px;
  width: 2px;
  height: 17px;
  margin-inline-start: -1px;
  border-radius: 1px;
  background: var(--text-dim);
  transform: rotate(42deg);
  box-shadow: -1px 0 0 0 var(--surface);
}

[data-noannot].is-on { background: rgba(var(--t-reader), .22); border-color: var(--accent-deep); }
[data-noannot].is-on .rd-noannot__mark::before,
[data-noannot].is-on .rd-noannot__mark::after { background: var(--accent-app); opacity: 1; }

/* Solange nichts markiert werden soll, gibt der Text die Auswahl
   nicht her. Das ist die halbe Miete: ohne Auswahl kein Griff, und
   das lange Drücken auf dem Telefon läuft ins Leere, statt jedes Mal
   die Lupe hochzuziehen. Bestehende Markierungen bleiben sichtbar. */
.rd-read.is-noannot .rd-flow {
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}

.rd-read.is-noannot [data-annot] { cursor: default; }



.rd-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.rd-head__titles { flex: 1; min-width: 0; }

.rd-head__h { min-width: 0; }

/* Der Titel ist ein Knopf – er führt zu "Information". Aussehen soll
   er trotzdem wie eine Überschrift: ein Knopf, der sich als solcher
   aufdrängt, säße hier nur im Weg. Beim Überfahren zeigt er, dass er
   einer ist. */
.rd-head__title {
  display: block;
  max-width: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 15px;
  font-weight: 500;
  text-align: start;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color var(--dur) var(--ease-out);
}

.rd-head__title:hover { color: var(--accent-app); }

.rd-head__author {
  font-size: 12px;
  color: var(--text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Werkzeugleiste – erscheint mit den Leisten beim Tipp in die Mitte */

.rd-tools {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 4px;
  overflow-x: auto;
  scrollbar-width: none;
}

.rd-tools::-webkit-scrollbar { display: none; }

/* Die Knöpfe stehen auf dem Text des Buches. Ohne eigene Kontur gehen
   sie darin unter – die Akzentfarbe trennt sie von der Seite. */
.rd-tool {
  flex: none;
  height: 32px;
  padding: 0 14px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent-deep) 22%, var(--surface));
  border: 1px solid var(--accent-deep);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--accent-app);
  white-space: nowrap;
  transition: background-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}

.rd-tool:hover { background: var(--accent-app); border-color: var(--accent-app); color: var(--ink); }
.rd-tool:active { transform: scale(.95); }



.rd-stagewrap { position: absolute; inset: 0; }

/* Beim Blättern endet die Seite über der Fortschrittszeile.
   Die Zeile bleibt immer stehen – auch im Vollbild und im ruhigen
   Modus – und lag damit auf der letzten Zeile jeder Seite. Ihre Höhe
   meldet read.js als --rd-foot-h, weil sie auf schmalen Geräten
   umbricht und keine feste Zahl hat.

   Nur im Blättermodus: beim Scrollen läuft der Text weiter unter der
   Zeile durch, und wer weiterrollt, holt sich die Zeile von selbst
   wieder frei. Dort bleibt inset: 0. */
.rd-read:not([data-reading="scroll"]) .rd-stagewrap {
  bottom: calc(var(--rd-foot-h, 0px) + 8px);
}

.rd-stage {
  position: relative;
  height: 100%;
  overflow: hidden;
  padding: var(--rd-margin, 22px);
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--rd-line);
}

[data-reading="scroll"] .rd-stage { overflow-y: auto; scrollbar-width: thin; }

/* Die Tinte des Buches. Drei Stufen, wie im gedruckten Buch:
   Fließtext, Überschrift, Zurückgenommenes (Zitat, Unterschrift).
   Gemessen auf --surface: 13,9 : 1 · 16,1 : 1 · 9,6 : 1. Der E-ink-Modus
   setzt alle drei auf Schwarz (styles/eink.css). */
.rdr {
  --rd-ink: #e9e5df;
  --rd-ink-strong: #f7f3ed;
  --rd-ink-soft: #c9c2b8;
}

.rd-flow {
  color: var(--rd-ink);
  transition: transform 240ms var(--ease-out);
  will-change: transform;
  font-kerning: normal;
  font-variant-ligatures: common-ligatures;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
}

/* Der unsichtbare Zwilling, in dem Kapitel nur gezählt werden. */
.rd-flow--ghost {
  position: absolute;
  inset-inline-start: -10000px;
  top: 0;
  visibility: hidden;
  pointer-events: none;
  transition: none;
}

/* Ein Abschnitt je Kapitel. Beim Blättern ist genau einer da; beim
   Scrollen stehen mehrere untereinander, damit das Buch durchläuft. */
.rd-ch { display: block; }

[data-reading="scroll"] .rd-ch + .rd-ch {
  margin-top: 1.6em;
  padding-top: 1.2em;
  border-top: 1px solid var(--rd-line);
}

/* ---------- Satz (seit 0.6.0 beta) ------------------------------------------

   Was hier steht, hat app/reader/typeset.js vorbereitet: jedes Buch,
   gleich welches Format, kommt mit denselben Klassen an. Die Gestaltung
   des Verlags ist dabei auf ihre Bedeutung reduziert (rd-c zentriert,
   rd-i kursiv …) – Farbe, Schrift und Maß macht der Reader.

   Absätze: [data-para] am Fließtext. „indent" ist der Satz des
   gedruckten Buches – kein Abstand, die erste Zeile eingerückt, nur
   nicht nach einer Überschrift oder einem Szenenwechsel. „space" ist der
   Abstand von früher. */

.rd-flow p {
  margin: 0 0 var(--rd-para, 8px);
  text-wrap: pretty;
  orphans: 2;
  widows: 2;
}
.rd-flow p:last-child { margin-bottom: 0; }

.rd-flow[data-para="indent"] p { margin: 0; }
.rd-flow[data-para="indent"] p + p { text-indent: 1.4em; }
.rd-flow[data-para="indent"] p.rd-first,
.rd-flow[data-para="indent"] p.rd-ni,
.rd-flow[data-para="indent"] p.rd-c,
.rd-flow[data-para="indent"] p.rd-r,
.rd-flow[data-para="indent"] p.rd-orntext,
.rd-flow[data-para="indent"] p.rd-verse,
.rd-flow[data-para="indent"] p.rd-cap,
.rd-flow[data-para="indent"] p.rd-fig,
.rd-flow[data-para="indent"] p.rd-subhead,
.rd-flow[data-para="indent"] p.rd-sbreak,
.rd-flow[data-para="indent"] p.rd-air,
.rd-flow[data-para="indent"] p.rd-cnum,
.rd-flow[data-para="indent"] p.rd-ctitle,
.rd-flow[data-para="indent"] p.rd-csub { text-indent: 0; }

/* Silbentrennung in der Sprache des Buches (lang am Fließtext). Ohne
   sie reißt der Blocksatz auf dem Telefon Löcher in jede Zeile. */
.rd-flow[data-hyph="on"] {
  -webkit-hyphens: auto;
  hyphens: auto;
  hyphenate-limit-chars: 6 3 2;
}

/* ---------- Kapitelanfang ------------------------------------------------------

   Nummer (klein, gesperrt, in der Farbe des Bereichs), Titel (groß, in
   der Schrift des Buches – Newsreader schaltet bei dieser Größe von
   selbst auf ihren Titelschnitt), Untertitel (kursiv), darunter eine
   Linie mit Sechseck. Beim Blättern beginnt jedes Kapitel auf einer
   neuen Seite und rutscht ein Stück tiefer, wie im gedruckten Buch. */

.rd-flow .rd-chead { margin-top: min(12vh, 3.6em); }
[data-reading="scroll"] .rd-flow .rd-chead { margin-top: .6em; }

.rd-flow .rd-cnum {
  margin: 0 0 .75em;
  font-family: var(--font);
  font-size: .72em;
  font-weight: 600;
  font-style: normal;
  line-height: 1.4;
  letter-spacing: .22em;
  text-transform: uppercase;
  text-align: center;
  text-indent: 0;
  color: var(--accent-app);
}

.rd-flow .rd-ctitle,
.rd-flow h1.rd-ctitle, .rd-flow h2.rd-ctitle, .rd-flow h3.rd-ctitle,
.rd-flow h4.rd-ctitle, .rd-flow h5.rd-ctitle, .rd-flow h6.rd-ctitle {
  margin: 0 0 .3em;
  font-size: calc(1em * var(--rd-head, 1.3) * 1.28);
  font-weight: 400;
  font-style: normal;
  line-height: 1.16;
  letter-spacing: -.005em;
  text-align: center;
  text-indent: 0;
  text-transform: none;
  font-variant-caps: normal;
  color: var(--rd-ink-strong);
  text-wrap: balance;
  -webkit-hyphens: manual;
  hyphens: manual;
}

/* Nur eine Zahl („7", „IV") – dann trägt sie den Anfang allein. */
.rd-flow .rd-ctitle.rd-cnumonly {
  font-size: calc(1em * var(--rd-head, 1.3) * 1.9);
  font-weight: 300;
  letter-spacing: .04em;
}

.rd-flow .rd-csub {
  margin: 0 0 .3em;
  font-size: 1.04em;
  font-weight: 400;
  font-style: italic;
  text-align: center;
  text-indent: 0;
  color: var(--rd-ink-soft);
}

.rd-flow .rd-chend::after {
  content: '';
  display: block;
  width: 7.5em;
  height: .9em;
  margin: 1.05em auto 1.9em;
  background: var(--accent-app);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 14'%3E%3Cpath d='M0 7h45M75 7h45' stroke='%23000' stroke-width='1'/%3E%3Cpath d='M60 1.6l5.4 3.1v6.2L60 14l-5.4-3.1V4.7z' fill='none' stroke='%23000' stroke-width='1.5' transform='translate(0 -.8)'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 14'%3E%3Cpath d='M0 7h45M75 7h45' stroke='%23000' stroke-width='1'/%3E%3Cpath d='M60 1.6l5.4 3.1v6.2L60 14l-5.4-3.1V4.7z' fill='none' stroke='%23000' stroke-width='1.5' transform='translate(0 -.8)'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Der erste Absatz eines Kapitels: erste Zeile in Kapitälchen oder ein
   Initial über drei Zeilen – je nach Format › Chapter start. */
.rd-flow[data-lead="caps"] .rd-lead::first-line {
  font-variant-caps: small-caps;
  letter-spacing: .035em;
}

.rd-flow[data-lead="drop"] .rd-lead[data-rd-drop]::first-letter {
  float: left;
  margin: .06em .1em 0 0;
  font-size: 3.5em;
  font-weight: 500;
  line-height: .8;
  color: var(--accent-app);
}

@supports (initial-letter: 3) or (-webkit-initial-letter: 3) {
  .rd-flow[data-lead="drop"] .rd-lead[data-rd-drop]::first-letter {
    float: none;
    margin: 0 .12em 0 0;
    font-size: inherit;
    line-height: inherit;
    -webkit-initial-letter: 3;
    initial-letter: 3;
  }
}

/* ---------- Überschriften im Kapitel ---------------------------------------------- */

.rd-flow h1, .rd-flow h2, .rd-flow h3, .rd-flow h4, .rd-flow h5, .rd-flow h6,
.rd-flow .rd-subhead {
  margin: 1.5em 0 .55em;
  font-size: calc(1em * var(--rd-head, 1.3));
  font-weight: 600;
  line-height: 1.25;
  text-indent: 0;
  color: var(--rd-ink-strong);
  text-wrap: balance;
  -webkit-hyphens: manual;
  hyphens: manual;
  break-after: avoid-column;
  break-inside: avoid;
}

.rd-flow h3 { font-size: calc(1em * max(1.05, var(--rd-head, 1.3) - .14)); }

/* Vor einem Bild, das mit ihr nicht in die Spalte passt, darf die
   Überschrift allein stehen – sonst bliebe die Seite davor leer. */
.rd-flow .rd-free { break-after: auto; }

.rd-flow h4, .rd-flow h5, .rd-flow h6, .rd-flow .rd-subhead {
  font-size: 1em;
  font-variant-caps: small-caps;
  letter-spacing: .05em;
  color: var(--accent-app);
}

.rd-flow > :first-child, .rd-ch > :first-child, .rd-ch > div:first-child > :first-child { margin-top: 0; }
.rd-flow .rd-chead:first-child { margin-top: min(12vh, 3.6em); }

/* ---------- Was der Verlag gemeint hat --------------------------------------------- */

.rd-flow .rd-c { text-align: center; text-indent: 0; -webkit-hyphens: manual; hyphens: manual; }
.rd-flow .rd-r { text-align: end; text-indent: 0; }
.rd-flow .rd-i { font-style: italic; }
.rd-flow .rd-b { font-weight: 600; }
.rd-flow .rd-sc { font-variant-caps: small-caps; letter-spacing: .03em; }
.rd-flow .rd-uc { text-transform: uppercase; letter-spacing: .04em; }
.rd-flow .rd-in { margin-inline-start: 1.5em; margin-inline-end: .5em; }
.rd-flow .rd-hang { padding-inline-start: 1.5em; text-indent: -1.5em; }
.rd-flow .rd-lg { font-size: 1.14em; }
.rd-flow .rd-sm { font-size: .88em; }
.rd-flow .rd-sup { vertical-align: super; font-size: .72em; line-height: 0; }
.rd-flow .rd-sub { vertical-align: sub; font-size: .72em; line-height: 0; }
.rd-flow .rd-u { text-decoration: underline; }
.rd-flow .rd-s { text-decoration: line-through; }
.rd-flow .rd-gap { margin-top: 1.4em; }
.rd-flow .rd-hide, .rd-flow .rd-pgnum, .rd-flow .rd-air { display: none; }

/* Ein Seitenumbruch des Verlags mitten im Kapitel: beim Blättern eine
   neue Seite, beim Scrollen nur Luft. */
.rd-read:not([data-reading="scroll"]) .rd-flow .rd-pb { break-before: column; }
[data-reading="scroll"] .rd-flow .rd-pb { margin-top: 1.6em; }

/* ---------- Szenenwechsel ------------------------------------------------------------

   <hr> und „* * *" bekommen ein Ornament aus Sechsecken. Ein Leerabsatz
   bleibt, was er im Druck ist: eine Leerzeile. Ein Sechseck an jeder
   Leerzeile wäre in einem Drama (Leerzeile zwischen jeder Rede) oder bei
   McCarthy (Leerzeile zwischen jedem Fragment) hunderte Male Lärm. Dass
   dort ein Wechsel ist, sagt auch am Seitenanfang der Absatz danach: er
   beginnt ohne Einzug (rd-first). */

.rd-flow hr, .rd-flow .rd-orn {
  height: .8em;
  width: 4.4em;
  margin: 1.4em auto;
  border: 0;
  background: var(--accent-app);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 66 12'%3E%3Cg fill='none' stroke='%23000' stroke-width='1.4'%3E%3Cpath d='M10 1.5l4.3 2.5v5L10 11.5 5.7 9V4z'/%3E%3Cpath d='M56 1.5l4.3 2.5v5L56 11.5 51.7 9V4z'/%3E%3C/g%3E%3Cpath d='M33 1l4.8 2.75v5.5L33 12l-4.8-2.75v-5.5z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 66 12'%3E%3Cg fill='none' stroke='%23000' stroke-width='1.4'%3E%3Cpath d='M10 1.5l4.3 2.5v5L10 11.5 5.7 9V4z'/%3E%3Cpath d='M56 1.5l4.3 2.5v5L56 11.5 51.7 9V4z'/%3E%3C/g%3E%3Cpath d='M33 1l4.8 2.75v5.5L33 12l-4.8-2.75v-5.5z'/%3E%3C/svg%3E") center / contain no-repeat;
  break-after: avoid-column;
}

.rd-flow .rd-orntext {
  margin: 1.2em 0;
  text-align: center;
  text-indent: 0;
  letter-spacing: .5em;
  color: var(--accent-app);
}

/* Das geschützte Leerzeichen darin bleibt Text (Lesezeichen zählen es
   mit) – es wird nur unsichtbar, nicht entfernt. */
.rd-flow .rd-sbreak {
  height: 1em;
  margin: 0;
  overflow: hidden;
  color: transparent;
}

/* ---------- Verse, Zitate, Mottos ------------------------------------------------------ */

.rd-flow .rd-verse {
  margin: .7em 0 .7em 1.2em;
  text-align: start;
  text-indent: 0;
  -webkit-hyphens: manual;
  hyphens: manual;
}

.rd-flow blockquote {
  margin: 1em 0 1em .4em;
  padding-inline-start: 1em;
  border-inline-start: 2px solid color-mix(in srgb, var(--accent-app) 55%, transparent);
  color: var(--rd-ink-soft);
}

.rd-flow blockquote.rd-epi {
  max-width: 84%;
  margin: 0 0 1.9em auto;
  padding: 0;
  border: 0;
  font-size: .92em;
  font-style: italic;
}
.rd-flow blockquote.rd-epi .rd-r,
.rd-flow blockquote.rd-epi .rd-i { font-style: normal; }

/* ---------- Bilder ------------------------------------------------------------------------ */

.rd-flow .rd-fig { margin: 1em 0; text-align: center; text-indent: 0; }
.rd-flow .rd-chimg { text-align: center; }

.rd-flow .rd-cap {
  margin: .2em 0 1.3em;
  font-size: .84em;
  font-style: italic;
  text-align: center;
  text-indent: 0;
  color: var(--rd-ink-soft);
}

/* Ein Kapitel aus nichts als einem Bild (Cover, Karte, Tafel): beim
   Blättern mittig auf seiner eigenen Seite. */
.rd-read:not([data-reading="scroll"]) .rd-flow .rd-imgpage {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: calc(var(--rd-colh, 70vh) - 2px);
}

/* ---------- Fußnoten ---------------------------------------------------------------------

   Das Zeichen ist klein, der Finger nicht: die Trefferfläche ist größer
   als die Ziffer (Polster, das die Zeile nicht verschiebt). */

.rd-flow a.rd-nref {
  position: relative;
  padding: .45em .28em;
  margin: -.45em -.08em;
  font-size: .72em;
  font-weight: 600;
  line-height: 0;
  vertical-align: super;
  text-decoration: none;
  color: var(--accent-app);
}
.rd-flow sup a.rd-nref, .rd-flow .rd-sup a.rd-nref { font-size: 1em; vertical-align: baseline; }
.rd-flow .rd-note { font-size: .9em; }

/* ---------- Listen, Tabellen, Code ---------------------------------------------------------- */

.rd-flow ul, .rd-flow ol { margin: .6em 0 .9em; padding-inline-start: 1.5em; }
.rd-flow li { margin: .25em 0; }
.rd-flow li > p { margin: 0; text-indent: 0; }

.rd-flow pre {
  margin: 1em 0;
  padding: .7em .9em;
  border-inline-start: 2px solid var(--rd-line);
  background: rgba(var(--o), .045);
  font-family: var(--font-mono);
  font-size: .8em;
  line-height: 1.5;
  text-align: start;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  -webkit-hyphens: none;
  hyphens: none;
}
.rd-flow code { font-family: var(--font-mono); font-size: .86em; }
.rd-flow pre code { font-size: 1em; }

/* Ein Bild darf nie höher sein als die Seite, sonst schiebt es sich in
   die nächste Spalte und hinterlässt dort eine leere Seite – genau das
   passiert bei Cover-Seiten, die aus nichts als einem Bild bestehen.
   Deshalb: Höhe deckeln, nicht umbrechen, keine Ränder, die addieren. */
.rd-flow img, .rd-flow svg {
  max-width: 100%;
  /* Nicht in Prozent: der Absatz um das Bild hat keine feste Höhe, an
     der ein Prozentwert hängen könnte. Die Spaltenhöhe kommt deshalb
     als Zahl aus applyFormat(). */
  /* Der Abzug ist der eigene Rand: ohne ihn wäre das Bild exakt so
     hoch wie die Spalte und die Ränder schöben es doch wieder hinaus. */
  max-height: calc(var(--rd-colh, 70vh) - 1.2em);
  height: auto;
  margin: .3em auto;
  object-fit: contain;
  border-radius: 4px;
  break-inside: avoid;
  page-break-inside: avoid;
}

.rd-flow a[data-rd-jump], .rd-flow a[data-rd-href] {
  color: var(--accent-app);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
}
.rd-flow a.rd-nref { text-decoration: none; }
.rd-flow table { width: 100%; margin: 1em 0; font-size: .88em; border-collapse: collapse; text-indent: 0; }
.rd-flow td, .rd-flow th { border: 1px solid var(--rd-line); padding: 4px 6px; text-align: start; -webkit-hyphens: manual; hyphens: manual; }
.rd-flow th { font-weight: 600; background: rgba(var(--o), .045); }

/* ---------- Seiten: Ton, Verweise ----------------------------------------------------------

   Format › Pages › Page tone. Ein weißes PDF leuchtet im dunklen
   Reader – „Dim" nimmt das Weiß zurück, „Dark" kehrt die Seite um
   (Schrift hell auf dunkel; Fotos werden dabei zu Negativen – darum
   nicht ab Werk), „Sepia" färbt warm. Auf E-ink nie. */

.rd-pdf[data-tone="dim"] .rd-pdfpage__canvas { filter: brightness(.82) contrast(1.04); }
.rd-pdf[data-tone="dark"] .rd-pdfpage__canvas { filter: invert(.9) hue-rotate(180deg) contrast(.96); }
.rd-pdf[data-tone="sepia"] .rd-pdfpage__canvas { filter: sepia(.42) brightness(.93) contrast(.98); }
.rd-pdf[data-tone="dark"] .rd-pdfpage,
.rd-pdf[data-tone="dim"] .rd-pdfpage { background: var(--surface-3); }

.rd-pdflinks { position: absolute; inset: 0; z-index: 2; }

.rd-pdflink {
  position: absolute;
  display: block;
  border-radius: 0;
  transition: background-color var(--dur) var(--ease-out);
}
.rd-pdflink:hover, .rd-pdflink:focus-visible {
  outline: 1px solid var(--accent-app);
  background: rgba(var(--t-reader), .16);
}

/* ---------- Fußnote im Blatt ---------------------------------------------------------------- */

.rd-notepop__text {
  max-height: min(52dvh, 420px);
  margin: 2px 0 16px;
  padding-inline-end: 4px;
  overflow-y: auto;
  font-size: 16px;
  line-height: 1.55;
  text-align: start;
  scrollbar-width: thin;
  will-change: auto;
}
.rd-notepop__text p { margin: 0 0 .6em; text-indent: 0; }
.rd-notepop__text .rd-hide { display: block; }

/* ---------- Welche Dateien gehen – und was nicht ------------------------------------------- */

.rd-fmt { display: grid; gap: 10px; }

.rd-fmt__row {
  display: grid;
  gap: 7px;
  padding: 12px 14px;
  background: var(--g-47);
}

.rd-fmt__group {
  font-size: max(var(--fs-floor), 11.5px);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-subtle);
}

.rd-fmt__list { display: flex; flex-wrap: wrap; gap: 6px; }

.rd-fmt__tag {
  padding: 3px 9px;
  background: rgba(var(--t-reader), .16);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--accent-app);
}

.rd-fmt__tag.is-off {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--text-muted);
}

.rd-fmt__hint, .rd-fmt__drm { font-size: 12.5px; line-height: 1.45; color: var(--text-muted); }
.rd-fmt__drm { margin: 2px 2px 0; }

.rd-problem { display: grid; gap: 10px; }
.rd-problem__file { font-size: 12px; color: var(--text-subtle); overflow-wrap: anywhere; }

.rd-bulk__failed li { display: grid; gap: 2px; }
.rd-bulk__why { font-size: max(var(--fs-floor), 11.5px); color: var(--text-subtle); }

/* ---------- Format: Gruppen ------------------------------------------------------------------- */

.rd-set__group { display: grid; gap: 12px; }
.rd-set__group + .rd-set__group,
.rd-set__group + .rd-slider { padding-top: 14px; border-top: 1px solid var(--rd-line); }

.rd-set__head {
  margin: 0;
  font-size: max(var(--fs-floor), 11.5px);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-subtle);
}

.rd-set__label { margin: 2px 0 -6px; font-size: 13px; color: var(--text-muted); }

/* ---------- Verzeichnis: zu einer Seite ----------------------------------------------------- */

.rd-toc__go { display: flex; align-items: flex-end; gap: 8px; margin: 0 0 12px; }
.rd-toc__golabel { flex: 1; display: grid; gap: 4px; font-size: 12px; color: var(--text-muted); }
.rd-toc__go .rd-btn { flex: none; }
.rd-input[aria-invalid="true"] { box-shadow: inset 0 0 0 1px var(--danger); }

/* ---------- PDF ------------------------------------------------------------
   Ein PDF zeichnet die App selbst (app/reader/pdfdoc.js). Jede Seite
   bekommt ein Kästchen mit dem Seitenverhältnis der echten Seite; die
   Leinwand darin füllt es aus. Die Höhe steht dabei als Zahl am
   Element – nur so hat der Bildlauf schon eine Gesamthöhe, bevor auch
   nur eine Seite gezeichnet ist. */

.rd-pdf {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 100%;
}

/* Im Blättermodus liegt die eine Seite mittig in der Fläche. */
.rd-read:not([data-reading="scroll"]) .rd-pdf { justify-content: center; height: 100%; }

/* Beim Scrollen stehen sie untereinander, mit sichtbarer Fuge. */
[data-reading="scroll"] .rd-pdf { gap: 14px; padding-bottom: 14px; }

.rd-pdfpage {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  background: var(--g-01);
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 0 2px 14px rgba(var(--o-deep), .38);
}

.rd-pdfpage__canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* Bis die Seite da ist, steht ihre Nummer im leeren Kästchen – besser
   als eine weiße Fläche ohne Auskunft. Sobald gezeichnet ist, liegt
   die Leinwand darüber. */
.rd-pdfpage__no {
  position: absolute;
  font-size: 13px;
  letter-spacing: 1px;
  color: rgba(var(--t-cover), .32);
}

/* Gezeichnet: die Nummer hat ausgedient – auf einer bunten Comicseite
   stünde sie sonst mitten im Bild. */
.rd-pdfpage[data-drawn] .rd-pdfpage__no { display: none; }

.rd-pdfpage.is-failed { background: #2a2018; }
.rd-pdfpage.is-failed .rd-pdfpage__no { color: var(--accent-app); }

/* Die neue Seite kommt von der Seite herein, in die gelesen wird –
   bei RTL also andersherum. Kurz genug, um nicht im Weg zu sein. */
@keyframes rd-pdf-in-right {
  from { opacity: 0; transform: translateX(7%); }
  to   { opacity: 1; transform: none; }
}

@keyframes rd-pdf-in-left {
  from { opacity: 0; transform: translateX(-7%); }
  to   { opacity: 1; transform: none; }
}

.rd-pdfpage.is-in-right { animation: rd-pdf-in-right 200ms var(--ease-out); }
.rd-pdfpage.is-in-left  { animation: rd-pdf-in-left 200ms var(--ease-out); }

@media (prefers-reduced-motion: reduce) {
  .rd-pdfpage.is-in-right,
  .rd-pdfpage.is-in-left { animation: none; }
}

/* Tippflächen */

/* Die Zonen liegen über der Seite, aber unter allem, was man antippen
   können muss: der Balken einer Markierung gehört nach vorn, sonst
   fängt die Blätterfläche seine Knöpfe ab. */
.rd-zones { position: absolute; inset: 0; z-index: 1; pointer-events: none; }

/* Reine Grafik, kein Knopf.
   Ein Element über dem Text fängt alles ab, was der Text bräuchte:
   das Ziehen zum Markieren, den Bildlauf eines PDFs, den Tipp
   dazwischen. Erkannt werden die Flächen deshalb über ihre Geometrie
   (zoneAt in read.js) – hier wird nur gezeigt, wo sie liegen. */
.rd-zone {
  position: absolute;
  display: grid;
  place-items: center;
  border-radius: 10px;
  pointer-events: none;
  color: rgba(var(--o), .34);
  transition: background-color var(--dur) var(--ease-out);
}

.rd-zone.has-border {
  border: 1.5px solid rgba(var(--t-reader), .45);
  background: rgba(var(--t-reader), .05);
}

.rd-zone:active { background: rgba(var(--t-reader), .16); }
.rd-zone__mark { font-size: 22px; line-height: 1; }
.rd-zone:not(.has-border) .rd-zone__mark { opacity: 0; }

/* Die dritte Fläche holt die Leisten zurück. Sie wird gezeigt, ist
   aber kein Knopf: ein Element quer über den Text würde das Markieren
   unmöglich machen – erkannt wird sie an der Kürze der Berührung. */
.rd-zone--menu {
  pointer-events: none;
  border-style: dashed;
}

.rd-zone--menu .rd-zone__mark { font-size: 15px; letter-spacing: 2px; }

/* Fortschritt über der Reiterleiste */



.rd-foot__bar {
  height: 3px;
  margin-bottom: 7px;
  border-radius: 999px;
  background: rgba(var(--o), .12);
  overflow: hidden;
}

.rd-foot__bar span { display: block; height: 100%; background: var(--accent-app); }

.rd-foot__row {
  display: grid;
  grid-template-columns: 3.2rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  font-size: max(var(--fs-floor), 11.5px);
  color: var(--text-dim);
}

.rd-foot__left { color: var(--accent-app); font-weight: 600; }
.rd-foot__right { text-align: end; }

.rd-foot__mid { min-width: 0; text-align: center; }

.rd-foot__chapter {
  display: block;
  font-size: 12px;
  color: #e0dcd6;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rd-foot__sub { display: block; font-size: max(var(--fs-floor), 10.5px); color: var(--text-faint); }

/* Die schmale Fassung: eine einzige Zeile, höchstens halb so hoch
   wie die volle. Links das Kapitel, rechts die Seite im Buch – der
   Balken selbst bleibt als Haarlinie stehen, er ist der Grund, warum
   die Zeile überhaupt da ist. */

.rd-foot.is-min { padding: 3px 10px 4px; }

.rd-foot.is-min .rd-foot__bar { height: 2px; margin-bottom: 4px; }

.rd-foot__row--min {
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  font-size: max(var(--fs-floor), 11px);
}

/* Kein Umbruch, sonst wäre die "eine Zeile" auf schmalen Geräten
   plötzlich zwei – der Kapitelname wird gekürzt, die Seitenzahl
   bleibt vollständig. */
.rd-foot__row--min .rd-foot__chapter {
  font-size: max(var(--fs-floor), 11px);
  text-align: start;
  line-height: 1.35;
}

.rd-foot__row--min .rd-foot__right { flex: none; white-space: nowrap; }

.rd-foot__inchap { color: var(--accent-app); }

.rd-foot__row--time {
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  margin-top: 4px;
  font-size: max(var(--fs-floor), 10.5px);
  color: var(--text-faint);
}

.rd-foot__row--time > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rd-foot__row--time > :last-child { text-align: end; }

.rd-foot__goal {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--rd-line);
}

.rd-foot__goal.is-done { border-color: var(--accent-deep); color: var(--accent-app); }

/* Zielring – ein Kreis, dessen Füllung aus --ratio kommt */

.rd-goalring {
  width: 14px;
  height: 14px;
  flex: none;
  border-radius: 50%;
  background:
    conic-gradient(var(--accent-app) calc(var(--ratio, 0) * 360deg),
                   rgba(var(--o), .14) 0);
  mask: radial-gradient(circle, transparent 52%, #000 54%);
  -webkit-mask: radial-gradient(circle, transparent 52%, #000 54%);
}

.rd-goalring--lg {
  position: relative;
  width: 84px;
  height: 84px;
  display: grid;
  place-items: center;
  mask: none;
  -webkit-mask: none;
  background:
    conic-gradient(var(--accent-app) calc(var(--ratio, 0) * 360deg),
                   rgba(var(--o), .12) 0);
}

.rd-goalring--lg::after {
  content: "";
  position: absolute;
  inset: 9px;
  border-radius: 50%;
  background: var(--surface);
}

.rd-goalring--lg b {
  position: relative;
  z-index: 1;
  font-size: 17px;
  color: var(--accent-app);
}

.rd-goalring--lg.is-done b { color: #82f5cb; }

/* Der Rückweg aus einem Verweis.

   Er steht über der Fortschrittszeile und nur dann, wenn es wirklich
   etwas zurückzugehen gibt. Kein Dauerknopf: was immer da ist, sieht
   man nach zwei Tagen nicht mehr. Der Sockel ist derselbe wie bei den
   Knöpfen der App – ein Rechteck mit Tiefe, kein Rund. */
.rd-back {
  position: absolute;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  bottom: calc(var(--rd-foot-b, 6px) + var(--rd-foot-h, 0px) + 10px);
  z-index: 7;

  display: flex;
  align-items: center;
  gap: 8px;
  max-width: calc(100% - 32px);
  padding: 9px 15px;

  --cut: 8px;
  clip-path: var(--cut-clip);
  background: var(--surface-2);
  box-shadow: 0 8px 22px rgba(var(--o-deep), .45);

  font-size: 13px;
  font-weight: 600;
  color: var(--accent-app);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rd-back__arrow {
  width: 8px;
  height: 8px;
  flex: none;
  border-inline-start: 2px solid var(--accent-app);
  border-bottom: 2px solid var(--accent-app);
  transform: rotate(45deg);
}

.rd-back:active { transform: translate(-50%, 1px); }

/* Auf Papier trägt die Fläche den Streifen, nicht der Schatten – und
   auch kein Rahmen: der Eckschnitt (clip-path) schneidet ihn mit weg. */
html[data-eink] .rd-back { box-shadow: none; background: #e0e0e0; color: #1c1c1c; }

/* Inhaltsverzeichnis

   EINE Rollfläche: das Fenster selbst (.pop, max-height 88dvh). Die
   Liste hatte vorher ihre eigene, mit fester Höhe – zwei Rollflächen
   ineinander, und der Finger erwischte die falsche. Kopf und Suchfeld
   bleiben beim Rollen stehen, damit der Rückweg immer erreichbar ist. */

.rd-pop--toc .pop__head,
.rd-pop--toc .rd-toc__search {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface);
}

.rd-pop--toc .rd-toc__search { top: 52px; padding: 6px 0 10px; display: block; }

.pop__body--toc { gap: 0; }

.rd-toc { display: grid; gap: 2px; }

.rd-toc__empty {
  padding: 18px 10px;
  font-size: 13.5px;
  color: var(--text-faint);
  text-align: center;
}

.rd-tocrow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 10px;
  border-radius: 7px;
  font-size: 14px;
  text-align: start;
  transition: background-color var(--dur) var(--ease-out);
}

/* Unterpunkte rücken ein und treten zurück: die Gliederung des Buches
   ist eine Auskunft, keine zweite Liste. */
.rd-tocrow[data-depth="1"] { padding-inline-start: 26px; font-size: 13.5px; }
.rd-tocrow[data-depth="2"] { padding-inline-start: 42px; font-size: 13px; }
.rd-tocrow[data-depth="3"] { padding-inline-start: 58px; font-size: 13px; }
.rd-tocrow[data-depth="4"] { padding-inline-start: 74px; font-size: 13px; }

.rd-tocrow:not([data-depth="0"]) .rd-tocrow__label { color: var(--text-muted); }

.rd-tocrow__label { min-width: 0; }

.rd-tocrow:hover { background: var(--g-42); }
.rd-tocrow.is-on { background: rgba(var(--t-reader), .16); color: var(--accent-app); }
.rd-tocrow.is-on .rd-tocrow__label { color: var(--accent-app); }
.rd-tocrow__page { flex: none; font-size: max(var(--fs-floor), 11.5px); color: var(--text-faint); }

/* =========================================================
   Einstellungen des Lesebildschirms
   ========================================================= */

.rd-set { display: grid; gap: 14px; }

.rd-fonts { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: thin; }

.rd-font {
  flex: none;
  display: grid;
  justify-items: center;
  gap: 2px;
  min-width: 62px;
  padding: 8px 6px;
  border-radius: 8px;
  background: var(--g-47);
  border: 1px solid transparent;
  font-size: 19px;
  color: #ddd8d1;
}

.rd-font span { font-size: max(var(--fs-floor), 10px); font-family: var(--font); color: var(--text-faint); }
.rd-font.is-on { border-color: var(--accent-app); color: var(--accent-app); }

.rd-slider { display: grid; gap: 6px; }

.rd-slider__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 13px;
  color: var(--text-dim);
}

.rd-slider__top b { color: var(--accent-app); font-size: 12.5px; }

.rd-slider input[type="range"] {
  width: 100%;
  accent-color: var(--accent-app);
}

.rd-check {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  cursor: pointer;
}

.rd-check input { position: absolute; opacity: 0; width: 0; height: 0; }

.rd-check__box {
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: 5px;
  border: 2px solid var(--line-strong);
  transition: background-color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}

.rd-check input:checked + .rd-check__box {
  background: var(--accent-app) center / 62% no-repeat;
  border-color: var(--accent-app);
  box-shadow: inset 0 0 0 3px var(--surface), inset 0 0 0 12px var(--accent-app);
}

/* Der Schalter steht jetzt einmal in styles/components.css – dieselbe
   Form wie der in der Layer-Liste. Hier stand eine Kapsel mit
   border-radius 999px; sie hat den gemeinsamen Bauplan überstimmt,
   weil reader.css später geladen wird als components.css. */


/* Tippflächen-Vorschau */

.rd-zonegrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }

.rd-zp { display: grid; justify-items: center; gap: 6px; }

.rd-zp__page {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  border-radius: 6px;
  background: var(--g-47);
  border: 1.5px solid var(--line-strong);
  overflow: hidden;
}

.rd-zp.is-on .rd-zp__page { border-color: var(--accent-app); border-width: 2px; }
.rd-zp.is-on .rd-zp__label { color: var(--accent-app); font-weight: 600; }

/* Die Flächen füllen die Vorschau wirklich aus – so, wie sie später
   auch auf der Seite liegen. */
.rd-zp__rect {
  position: absolute;
  display: grid;
  place-items: center;
  font-size: 12px;
  line-height: 1;
}

.rd-zp__rect.is-turn {
  border: 1px solid rgba(var(--t-reader), .75);
  background: rgba(var(--t-reader), .18);
  color: var(--accent-app);
}

.rd-zp__rect.is-menu {
  border: 1px dashed rgba(var(--o), .18);
  font-size: max(var(--fs-floor), 8px);
  letter-spacing: 1px;
  color: var(--text-faint);
}

.rd-zp__label { font-size: max(var(--fs-floor), 11px); color: var(--text-dim); }

.rd-legend {
  display: flex;
  gap: 16px;
  justify-content: center;
  font-size: max(var(--fs-floor), 11px);
  color: var(--text-faint);
}

.rd-legend span { display: inline-flex; align-items: center; gap: 5px; }

.rd-legend i {
  width: 12px;
  height: 10px;
  border-radius: 2px;
}

.rd-legend i.is-turn {
  border: 1px solid rgba(var(--t-reader), .75);
  background: rgba(var(--t-reader), .18);
}

.rd-legend i.is-menu { border: 1px dashed rgba(var(--o), .22); }

.rd-optrow {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--g-47);
  text-align: start;
}

.rd-optrow__body { flex: 1; display: grid; gap: 2px; }
.rd-optrow__name { font-size: 15px; }
.rd-optrow__hint { font-size: max(var(--fs-floor), 11.5px); color: var(--text-faint); }

.rd-optrow__mark {
  width: 18px;
  height: 18px;
  flex: none;
  border-radius: 50%;
  border: 2px solid var(--line-strong);
}

.rd-optrow.is-on .rd-optrow__mark {
  border-color: var(--accent-app);
  background: var(--accent-app);
  box-shadow: inset 0 0 0 3px var(--g-47);
}

/* =========================================================
   Markierungen im Text
   ========================================================= */

.ra {
  border-radius: 2px;
  background: color-mix(in srgb, var(--ra, #f6d68a) 34%, transparent);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  cursor: pointer;
}

.ra--sun  { --ra: #f6d68a; }
.ra--moss { --ra: #82f5cb; }
.ra--sky  { --ra: #98e2f5; }
.ra--rose { --ra: #f9b4c9; }
.ra--clay { --ra: #b08968; }

.ra.is-underline { border-bottom: 1.5px solid var(--ra); }
.ra.is-bold { font-weight: 700; }
.ra.has-note { box-shadow: 0 0 0 1px color-mix(in srgb, var(--ra) 55%, transparent); }

/* Der komplexe Block: eine Umrandung, die über Zeilen und Absätze
   hinweg zusammenhält – Anfang und Ende bekommen die Seitenkanten. */
.ra-cx {
  border-top: 1.5px solid var(--accent-deep);
  border-bottom: 1.5px solid var(--accent-deep);
  background: rgba(var(--t-reader), .09);
  padding: 2px 0;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  cursor: pointer;
}

.ra-cx--start { border-inline-start: 1.5px solid var(--accent-deep); padding-inline-start: 4px; border-radius: 4px 0 0 4px; }
.ra-cx--end { border-inline-end: 1.5px solid var(--accent-deep); padding-inline-end: 4px; border-radius: 0 4px 4px 0; }
.ra-cx.has-note { background: rgba(var(--t-reader), .16); }

/* Der Balken über der Auswahl */

.ra-pop {
  position: absolute;
  /* Über den Tippflächen: die liegen ebenfalls über der Seite und
     würden sonst jeden Druck auf diese Knöpfe abfangen. */
  z-index: 30;
  display: grid;
  gap: 8px;
  padding: 9px 10px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--accent-deep);
  box-shadow: var(--shadow-2);
  animation: pop-in 180ms var(--ease-spring) both;
}

.ra-pop__colors { display: flex; gap: 6px; justify-content: center; }
.ra-pop__colors--wide { justify-content: flex-start; }

.ra-color {
  width: 24px;
  height: 24px;
  border: 2px solid transparent;
}

.ra-pop__acts { display: flex; gap: 4px; }

.ra-act {
  padding: 5px 9px;
  border-radius: 6px;
  background: rgba(var(--o), .06);
  font-size: 12.5px;
  color: #e6e2dc;
}

.ra-act:hover { background: rgba(var(--o), .12); }
.ra-act.is-on { background: var(--accent-app); color: var(--ink); }
.ra-act--danger { color: #ff9a9a; }

/* Ziehpunkte an den Enden einer Markierung */

.ra-grip {
  position: absolute;
  z-index: 29;
  width: 18px;
  height: 18px;
  margin: -3px 0 0 -9px;
  border-radius: 50%;
  background: var(--accent-app);
  border: 2px solid var(--bg);
  box-shadow: 0 2px 8px rgba(var(--o-deep), .5);
  cursor: ew-resize;
  touch-action: none;
}

/* Der Strich nach oben zeigt, an welcher Kante der Punkt hängt. */
.ra-grip::before {
  content: "";
  position: absolute;
  inset-inline-start: 50%;
  bottom: 100%;
  width: 2px;
  height: 14px;
  margin-inline-start: -1px;
  background: var(--accent-app);
}

.ra-grip.is-dragging { transform: scale(1.25); }

.ra-quote, .rn-quote {
  margin: 0 0 12px;
  padding: 8px 12px;
  border-inline-start: 3px solid var(--mark, var(--accent-app));
  border-radius: 0 6px 6px 0;
  background: rgba(var(--o), .04);
  font-size: 14px;
  line-height: 1.55;
  color: #ddd8d1;
}

.ra-kinds { display: flex; gap: 8px; }

/* =========================================================
   Annotations-Reiter
   ========================================================= */

.rn-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 4px;
}

.rn-head__title {
  flex: 1;
  min-width: 0;
  font-size: 17px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rn-list { display: grid; gap: 4px; }

.rn-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 8px;
  border-radius: 8px;
  text-align: start;
  transition: background-color var(--dur) var(--ease-out);
}

.rn-row:hover { background: rgba(var(--o), .05); }

.rn-row__cover {
  width: 38px;
  aspect-ratio: 2 / 3;
  flex: none;
  object-fit: cover;
  border-radius: 4px;
  background: var(--surface-2);
}

.rn-row__body { flex: 1; min-width: 0; display: grid; gap: 2px; }

.rn-row__title {
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rn-row__meta { font-size: max(var(--fs-floor), 11.5px); color: var(--text-faint); }

.rn-row__count {
  flex: none;
  min-width: 26px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--accent-app);
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
  text-align: center;
}

.rn-block {
  position: relative;
  margin-bottom: 14px;
  padding: 12px;
  border-radius: 10px;
  border: 1.5px solid var(--accent-deep);
  background: rgba(var(--t-reader), .07);
  scroll-margin: 90px;
}

/* Eingeklappt bleibt die Überschrift – das genügt, um den Block
   wiederzuerkennen, und die Liste bleibt überschaubar. */
.rn-block.is-shut { background: rgba(var(--t-reader), .04); }
.rn-block.is-shut .rn-block__head { margin-bottom: 6px; }
.rn-block.is-shut .rn-block__note { margin-bottom: 0; font-size: 14px; }

.rn-block.is-flash { animation: rn-flash 900ms var(--ease-out); }

@keyframes rn-flash {
  0%   { box-shadow: 0 0 0 0 rgba(var(--t-reader), .55); }
  40%  { box-shadow: 0 0 0 6px rgba(var(--t-reader), .30); }
  100% { box-shadow: 0 0 0 0 rgba(var(--t-reader), 0); }
}

/* Der Falt-Knopf: ein Winkel, der sich dreht. */
.rn-block__fold {
  width: 22px;
  height: 22px;
  flex: none;
  position: relative;
  border-radius: 6px;
}

.rn-block__fold::before {
  content: "";
  position: absolute;
  inset-inline-start: 6px;
  top: 7px;
  width: 7px;
  height: 7px;
  border-inline-end: 2px solid var(--accent-app);
  border-bottom: 2px solid var(--accent-app);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease-out);
}

.rn-block__fold:hover { background: rgba(var(--t-reader), .16); }
.rn-block.is-shut .rn-block__fold::before { transform: rotate(-45deg); }

.rn-block__count {
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(var(--o), .07);
  font-size: max(var(--fs-floor), 10.5px);
  color: var(--text-dim);
}

/* ---------- Seitenleiste: von Markierung zu Markierung ------------------- */

/* Schlicht und am Rand: zusammengeklappt sind es nur Striche, halb
   durchscheinend, damit sie nichts verdecken. Sie klebt in der Mitte
   der rechten Bildschirmkante – dort, wo der Daumen ist. */
.rn-rail {
  position: fixed;
  inset-inline-end: 2px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 8;
  display: flex;
  align-items: center;
  max-height: 60dvh;
  padding: 6px 2px;
  border-radius: 10px;
  opacity: .45;
  transition: opacity var(--dur) var(--ease-out),
              background-color var(--dur) var(--ease-out);
}

.rn-rail:hover,
.rn-rail.is-open {
  opacity: 1;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
}

.rn-rail__rows {
  display: grid;
  gap: 2px;
  max-height: 56dvh;
  overflow-y: auto;
  scrollbar-width: none;
}

.rn-rail__rows::-webkit-scrollbar { display: none; }

.rn-rail__row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  width: 22px;
  padding: 4px 6px 4px 0;
  transition: width var(--dur) var(--ease-out);
}

/* Zusammengeklappt: nur der Strich. Ausgeklappt: der Anfang der Notiz –
   dieselbe Leiste, nur breiter. */
.rn-rail__text {
  flex: 1;
  min-width: 0;
  font-size: max(var(--fs-floor), 11.5px);
  text-align: end;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out);
}

.rn-rail__dash {
  width: 14px;
  height: 2px;
  flex: none;
  border-radius: 2px;
  background: var(--mark, var(--text-faint));
  opacity: .55;
  transition: width var(--dur) var(--ease-out), opacity var(--dur) var(--ease-out);
}

.rn-rail__row:hover .rn-rail__dash,
.rn-rail__row.is-on .rn-rail__dash { opacity: 1; width: 20px; }
.rn-rail__row.is-on .rn-rail__text { color: var(--accent-app); }

.rn-rail.is-open .rn-rail__row,
.rn-rail:hover .rn-rail__row { width: min(210px, 44vw); }

.rn-rail.is-open .rn-rail__text,
.rn-rail:hover .rn-rail__text { opacity: 1; }

.rn-block__head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }

/* Was was ist, steht dran: der Block trägt die Akzentfarbe, eine
   einfache Markierung ihre eigene. */
.rn-kind {
  flex: none;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: max(var(--fs-floor), 10px);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.rn-kind--complex { background: var(--accent-deep); color: var(--ink); }

.rn-kind--simple {
  background: var(--mark, var(--accent-app));
  color: var(--ink);
}

/* Die Notiz ist die Überschrift ihrer Markierung – sie sagt, warum die
   Stelle überhaupt markiert wurde. */
.rn-block__note {
  margin-bottom: 10px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--accent-app);
}

.rn-block__hint,
.rn-child__hint {
  font-size: max(var(--fs-floor), 11.5px);
  font-style: italic;
  color: var(--text-faint);
}

.rn-block__hint { margin-bottom: 10px; }

/* Die Textstelle des Blocks – hier darf markiert werden, deshalb ist
   sie echter Text und kein Bild einer Stelle. */
.rn-passage {
  margin: 0 0 12px;
  padding: 10px 12px;
  border-inline-start: 3px solid var(--accent-deep);
  border-radius: 0 6px 6px 0;
  background: rgba(var(--o), .04);
  font-size: 14px;
  line-height: 1.6;
  color: #ddd8d1;
  white-space: pre-wrap;
  user-select: text;
  -webkit-user-select: text;
}

.rn-passage .ra { cursor: help; }

.rn-child__head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }

.rn-child__note {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
  color: #e7e3dd;
}

.rn-block__place { flex: 1; font-size: max(var(--fs-floor), 11.5px); color: var(--text-faint); }

.rn-block__act {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 6px;
}

.rn-block__act img { width: 15px; opacity: .8; }
.rn-block__act:hover { background: rgba(var(--o), .08); }

.rn-note {
  padding: 8px 10px;
  border-radius: 6px;
  background: rgba(var(--o), .04);
  font-size: 13.5px;
  line-height: 1.55;
  color: #cfcac3;
}

.rn-children { display: grid; gap: 8px; margin: 12px 0 4px; padding-inline-start: 10px;
               border-inline-start: 1px dashed var(--accent-deep); }

.rn-child { cursor: pointer; }
.rn-child .rn-quote { margin-bottom: 6px; font-size: 13px; }

.rn-jump {
  margin-top: 10px;
  font-size: 12px;
  color: var(--accent-app);
  text-decoration: underline;
}

.rn-simples { display: grid; gap: 4px; }

.rn-simple {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  padding: 9px 8px;
  border-radius: 8px;
  text-align: start;
  transition: background-color var(--dur) var(--ease-out);
}

.rn-simple:hover { background: rgba(var(--o), .05); }

.rn-simple__dot {
  width: 10px;
  height: 10px;
  margin-top: 5px;
  flex: none;
  border-radius: 50%;
}

.rn-simple__body { flex: 1; min-width: 0; display: grid; gap: 3px; }

.rn-simple__text {
  font-size: 13.5px;
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.rn-simple__note { font-size: max(var(--fs-floor), 11.5px); color: var(--text-faint); }
.rn-simple__place { flex: none; font-size: max(var(--fs-floor), 11px); color: var(--text-faint); }

/* Review */

.rn-startrow { display: flex; gap: 10px; margin-top: 14px; }

.rn-review { display: grid; gap: 14px; }

.rn-review__top { display: flex; align-items: center; justify-content: space-between; }
.rn-review__count { font-size: 13px; color: var(--text-dim); }

/* Die Karte hat eine feste Höhe, und der Text darin scrollt. Ohne das
   lief eine lange komplexe Stelle über die Knöpfe darunter hinweg. */
.rn-card {
  display: block;
  width: 100%;
  height: min(56dvh, 420px);
  perspective: 1000px;
  background: none;
}

.rn-card__inner {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 460ms var(--ease-out);
}

.rn-card.is-flipped .rn-card__inner { transform: rotateY(180deg); }

.rn-card__face {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: 12px;
  padding: 18px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--rd-line);
  border-top: 2px solid var(--accent-app);
  backface-visibility: hidden;
  text-align: center;
}

.rn-card__face--back { transform: rotateY(180deg); background: var(--surface-2); }

.rn-card__tag {
  font-size: max(var(--fs-floor), 11px);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.rn-card__text {
  align-self: center;
  max-height: 100%;
  overflow-y: auto;
  font-size: 15px;
  line-height: 1.55;
  color: #e7e3dd;
  scrollbar-width: thin;
}
.rn-card__hint { font-size: max(var(--fs-floor), 11px); color: var(--text-faint); }

.rn-review__acts { display: flex; gap: 8px; justify-content: space-between; }
.rn-review__acts .rd-btn { flex: 1; }

/* =========================================================
   Stats
   ========================================================= */

.rd-stats4 { grid-template-columns: repeat(4, 1fr); }
.rd-stats4 .mnt-stat__value { font-size: 15px; }
.rd-stats4 .mnt-stat__label { font-size: max(var(--fs-floor), 9.5px); }

.rd-sum { display: grid; gap: 2px; margin: 12px 0 10px; }
.rd-sum__value { font-size: 22px; font-weight: 600; color: var(--accent-app); }
.rd-sum__hint { font-size: max(var(--fs-floor), 11.5px); color: var(--text-faint); }

.rd-delta { font-size: 12.5px; color: var(--text-dim); }
.rd-delta.is-up { color: #82f5cb; }
.rd-delta.is-down { color: #ff9a9a; }

.rd-bars {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 132px;
  padding-top: 8px;
}

.rd-bars__empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 12px;
  color: var(--text-faint);
}

.rd-bar {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 4px;
  height: 100%;
}

.rd-bar__fill {
  display: block;
  flex: none;
  width: 100%;
  border-radius: 3px 3px 0 0;
  background: linear-gradient(to top, var(--accent-deep), var(--accent-app));
}

/* Ein Fach mit fester Höhe, auch wenn nichts drinsteht.
   Beschriftet wird nicht jeder Balken (im Monat jeder dritte). Ohne
   feste Höhe fiel die leere Zeile in sich zusammen, und die Balken
   ohne Beschriftung standen zwölf Pixel tiefer als die mit – als
   hätte man an jedem dritten Tag mehr gelesen. Alle Füllungen
   brauchen dieselbe Grundlinie. */
.rd-bar__label {
  height: 12px;
  line-height: 12px;
  font-size: max(var(--fs-floor), 9px);
  color: var(--text-faint);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
}

/* Der schwebende Hinweis über Balken und Heatmap-Feldern.

   Er liegt am <body>, nicht in der Karte: eine Karte scrollt, hat
   overflow und einen eigenen Stapelplatz – ein Kästchen darin wäre
   auf dem Telefon halb abgeschnitten. Angefasst wird er nie
   (pointer-events: none), sonst nähme er dem Balken darunter den
   nächsten Tipp weg. */
.rd-tip {
  position: fixed;
  z-index: 90;
  max-width: 70vw;
  padding: 6px 9px;
  border-radius: 8px;
  border: 1px solid var(--rd-line);
  background: color-mix(in srgb, var(--bg) 92%, var(--accent-deep));
  color: var(--text);
  font-size: 12px;
  line-height: 1.3;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 6px 20px rgba(var(--o-deep), .42);

  opacity: 0;
  visibility: hidden;
  transition: opacity 120ms var(--ease-out);
}

.rd-tip.is-on { opacity: 1; visibility: visible; }

@supports not (background: color-mix(in srgb, #000 50%, #fff)) {
  .rd-tip { background: var(--g-41); }
}

/* Ein Feld, das gerade erklärt wird, hebt sich ab – sonst rät man,
   welches von dreißig Quadraten gemeint ist. */
.rd-bar { cursor: default; }
.rd-bar:hover .rd-bar__fill { filter: brightness(1.18); }
.rd-heat__cell[data-tip]:hover { outline: 1px solid var(--accent-app); }

/* Heatmap */

.rd-heat__scroll { overflow-x: auto; padding: 10px 0 4px; scrollbar-width: thin; }
.rd-heat { display: flex; gap: 6px; }

.rd-heat__days {
  display: grid;
  grid-template-rows: repeat(7, 1fr);
  gap: 3px;
  font-size: max(var(--fs-floor), 8.5px);
  color: var(--text-faint);
}

.rd-heat__days span { display: grid; align-items: center; height: 13px; }

.rd-heat__grid {
  display: grid;
  grid-template-rows: repeat(7, 13px);
  grid-auto-flow: column;
  grid-auto-columns: 13px;
  gap: 3px;
}

.rd-heat__cell { border-radius: 3px; background: rgba(var(--o), .06); }
.rd-heat__cell.is-void { background: none; }
.rd-heat__cell.is-1 { background: rgba(var(--t-reader), .34); }
.rd-heat__cell.is-2 { background: rgba(var(--t-reader), .56); }
.rd-heat__cell.is-3 { background: rgba(var(--t-reader), .78); }
.rd-heat__cell.is-4 { background: var(--accent-app); }

.rd-heat__legend {
  display: flex;
  align-items: center;
  gap: 4px;
  justify-content: flex-end;
  font-size: max(var(--fs-floor), 10px);
  color: var(--text-faint);
}

.rd-heat__legend .rd-heat__cell { width: 12px; height: 12px; }

/* Ziel */

.rd-goal { display: flex; align-items: center; gap: 18px; }
.rd-goal__body { display: grid; gap: 4px; justify-items: start; }
.rd-goal__label { font-size: 15px; color: #e8e4de; }
.rd-goal__hint { font-size: 12px; color: var(--text-faint); }

/* Genres */

.rd-splitbar { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 12px; }
.rd-split { display: grid; gap: 8px; }

.rd-split__row {
  display: grid;
  grid-template-columns: minmax(64px, 1fr) 2fr auto;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
}

.rd-split__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.rd-split__track {
  height: 9px;
  border-radius: 999px;
  background: rgba(var(--o), .07);
  overflow: hidden;
}

.rd-split__fill { display: block; height: 100%; background: var(--accent-app); }
.rd-split__value { font-size: max(var(--fs-floor), 11.5px); color: var(--text-faint); }

/* Erinnerung an das Leseziel */

.rd-remind {
  position: fixed;
  inset-inline-start: 50%;
  bottom: calc(var(--sh-tabs-h) + var(--safe-bottom) + 12px);
  transform: translateX(-50%);
  z-index: 65;
  display: flex;
  align-items: center;
  gap: 10px;
  width: min(420px, calc(100% - 32px));
  padding: 10px 14px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--c-reader-stroke);
  box-shadow: var(--shadow-2);
  font-size: 13px;
  animation: rd-remind-in 320ms var(--ease-spring) both;
}

.rd-remind span:nth-child(2) { flex: 1; }

.rd-remind button {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  font-size: 16px;
  color: var(--text-dim);
}

.rd-remind .rd-goalring { --accent-app: var(--c-reader); }

@keyframes rd-remind-in {
  from { opacity: 0; transform: translate(-50%, 14px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* Menü einer Kachel */

.rd-menu__meta { margin-bottom: 14px; font-size: 12.5px; color: var(--text-faint); }

@media (max-width: 360px) {
  .rd-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
  .rd-stats4 { grid-template-columns: repeat(2, 1fr); }
}

/* ==========================================================================
   Vorlesen (app/reader/tts.js)
   ========================================================================== */

/* Der Knopf trägt dasselbe Symbol wie die Meditation, nur invertiert –
   ein Lautsprecher heißt überall in der App dasselbe. */
[data-tts] img { width: 18px; }

[data-tts].is-on {
  background: rgba(var(--t-reader), .22);
  border-color: var(--accent-deep);
}

/* Im Scroll-Modus gibt es keine Seite, an deren Ende geblättert werden
   könnte. Der Knopf bleibt trotzdem stehen und sagt es – verschwände er,
   suchte man ihn. Kein `disabled`: das nähme ihm den Tooltip und den
   Fokus, und die Erklärung käme nirgends an. */
[data-tts].is-disabled { opacity: .38; }
[data-tts].is-disabled:hover { background: var(--surface); }

/* Ein Tippen auf den gesperrten Knopf antwortet wenigstens. */
[data-tts].is-nope { animation: rd-nope 380ms var(--ease-out); }

@keyframes rd-nope {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-3px); }
  75%      { transform: translateX(3px); }
}

/* ---------- Die Zeilenmarke ----------------------------------------------

   Sie liegt über dem Text, nicht darin: kein Zeigerziel, kein
   Auswahlhindernis, kein Eingriff in den Umbruch. Deshalb ein eigenes
   Element in .rd-stagewrap statt eines <mark> im Fluss – ein Element im
   Text änderte die Zeilenlänge und damit die Seitenzahl.
   ------------------------------------------------------------------------ */

.rd-tts-line {
  position: absolute;
  z-index: 3;
  pointer-events: none;
  border-radius: 4px;

  /* Deckend genug, um die Zeile zu finden, durchlässig genug, um sie zu
     lesen: der Text darüber behält seinen vollen Kontrast, weil die
     Marke dahinterliegt und nicht darauf. */
  background: rgba(var(--t-reader), .20);
  box-shadow: inset 0 0 0 1px rgba(var(--t-reader), .55);

  opacity: 0;
  transition: opacity var(--dur) var(--ease-out),
              transform var(--dur) var(--ease-out);
}

.rd-tts-line.is-on { opacity: 1; }

/* Wer die Bewegung nicht will, bekommt die Marke ohne sie. */
@media (prefers-reduced-motion: reduce) {
  .rd-tts-line { transition: none; }
}

/* ---------- Das Fenster --------------------------------------------------- */

/* --text-dim, nicht --text-faint: die Zwischenüberschrift ist 11 px
   und in Großbuchstaben, und mit --text-faint kam sie auf 3,4:1 gegen
   die Fläche des Fensters – unter den 4,5:1, die WCAG AA für Text
   dieser Größe verlangt. Mit --text-dim sind es 6,2:1. */
.rd-tts-h {
  margin: 6px 0 -4px;
  font-size: max(var(--fs-floor), 11px);
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.rd-tts-note {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--text-dim);
}

.rd-tts-voices {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.rd-tts-voice {
  flex: 1 1 92px;
  display: grid;
  gap: 1px;
  padding: 9px 10px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--rd-line);
  font-size: 13.5px;
  color: var(--text);
  text-align: start;
  transition: border-color var(--dur) var(--ease-out),
              background-color var(--dur) var(--ease-out);
}

.rd-tts-voice span { font-size: max(var(--fs-floor), 10.5px); color: var(--text-faint); }
.rd-tts-voice:hover { border-color: var(--accent-app); }

/* Die gewählte Stimme trägt den Akzent als Fläche. Die Schrift darauf
   ist --ink, nicht --text: auf dem hellen Akzent wäre helle Schrift
   nicht mehr lesbar (WCAG AA), und dieselbe Paarung benutzt schon
   .rd-btn und .rd-btn--ghost.is-on. */
.rd-tts-voice.is-on {
  background: var(--accent-app);
  border-color: var(--accent-app);
  color: var(--ink);
}

/* .72 lag mit 4,6:1 nur knapp über der Grenze – .8 macht 5,3:1 daraus,
   ohne dass die Zeile ihre Nachordnung verliert. */
.rd-tts-voice.is-on span { color: var(--ink); opacity: .8; }

/* Der Timer hat sieben Stufen – auf 390 px passen sie nicht in eine
   Zeile, also darf die Segmentleiste hier umbrechen. */
.rd-seg--wrap { flex-wrap: wrap; }
.rd-seg--wrap .rd-seg__btn { flex: 1 0 auto; }

.rd-tts-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.rd-tts-stat {
  display: grid;
  gap: 2px;
  padding: 10px 8px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--rd-line);
  text-align: center;
}

.rd-tts-stat b { font-size: 15px; color: var(--accent-app); }
.rd-tts-stat span { font-size: max(var(--fs-floor), 10.5px); color: var(--text-dim); }
/* Aus demselben Grund wie .rd-tts-h: 10,5 px sind kleiner Text, und
   der braucht 4,5:1. */
.rd-tts-stat i { font-size: max(var(--fs-floor), 10.5px); font-style: normal; color: var(--text-dim); }

/* Die Fortschrittszeile des ersten Starts: 88 MB brauchen eine Minute,
   und eine Minute ohne ein Wort sieht aus wie ein Fehler. Leer nimmt
   sie keinen Platz weg. */
.rd-tts-progress {
  margin: 0;
  min-height: 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--accent-app);
}

.rd-tts-progress:empty { display: none; }

.rd-tts-acts {
  display: flex;
  gap: 10px;
  margin-top: 6px;
}

.rd-tts-acts .rd-btn { flex: 1; }

/* Das Suchfeld über der Sprachliste. 56 Sprachen sind zu viele zum
   Scrollen – wer weiß, was er sucht, tippt drei Buchstaben. */
.rd-tts-search { margin: 2px 0 0; }

/* Die Liste bekommt eine feste Höhe und scrollt in sich. Ohne das
   wäre das Popup so lang wie das Verzeichnis, und Tempo, Timer und
   der Start-Knopf lägen unerreichbar darunter. */
.rd-tts-langs {
  display: grid;
  gap: 6px;
  max-height: 216px;
  overflow-y: auto;
  padding-inline-end: 4px;

  /* Der Rand macht sichtbar, dass hier etwas weitergeht. */
  border-bottom: 1px solid var(--rd-line);
  padding-bottom: 8px;
}

/* Die Zahl neben "Language": wie viele es überhaupt sind. Kleiner und
   ruhiger als die Überschrift, aber hell genug für AA. */
.rd-tts-h small {
  font-size: max(var(--fs-floor), 10px);
  letter-spacing: 0;
  color: var(--text-dim);
  opacity: .75;
}

/* Der Muttersprachenname steht hier nicht als Beiwerk, sondern als
   Information – auf Deutsch sucht man "Deutsch", nicht "German".
   .rd-optrow__hint ist mit --text-faint auf 3,95:1 zu blass dafür.
   Angehoben wird nur diese Liste: dieselbe Klasse trägt in den
   anderen Dialogen echte Nebensätze, die dunkler bleiben dürfen. */
.rd-tts-langs .rd-optrow__hint { color: var(--text-dim); }

/* =========================================================
   Die Seite hat eine Höchstbreite

   Eine Buchseite ist keine Fensterbreite. Auf 1280px liefe eine
   Zeile über gut 1200 Pixel, und das Auge findet den Anfang der
   nächsten nicht mehr – der klassische Grund, warum jedes Buch
   einen Satzspiegel hat und keinen Seitenrand von null.

   Die Grenze steht deshalb an der Fläche selbst und nicht am Text:
   --rd-page ist die Seite, --rd-margin ihr Rand (read.js setzt ihn
   nach der Formatierung). Damit stimmt alles andere von allein –
   `frame.clientWidth - 2 * margin` in app/reader/read.js ist genau
   die Spaltenbreite, die Tippflächen (zoneAt) rechnen gegen
   dieselbe Fläche, und die Markierungen sitzen, wo sie sitzen.

   Fest, nicht vom Fenster abgeleitet: die Seitenzahlen eines Buches
   sind ein Ergebnis der Spaltenbreite. Hinge sie am Fenster, hätte
   dasselbe Buch auf 936 und auf 1280 verschiedene Seitenzahlen, und
   ein Ziehen am Fensterrand verschöbe die Zählung mitten im Lesen.
   Über 720 + 2 · Rand ändert sich hier deshalb gar nichts mehr.
   Derselbe Wert steht als MAX_PAGE in app/reader/read.js.

   Im Rollmodus greift zusätzlich --measure: dort ist die Fläche eine
   Bahn, kein Blatt, und 65 Zeichen ist die Zeile, die man noch am
   Stück liest.
   ========================================================= */

:root { --rd-page: 720px; }

.rd-stage {
  /* + 2px: .rd-stage hat einen 1px-Rand, und box-sizing rechnet ihn in
     die Breite hinein. Ohne den Zuschlag blieben innen 718 statt 720
     stehen, und die Grenze in app/reader/read.js (MAX_PAGE) und die
     hier meinten zwei verschiedene Zahlen. */
  max-width: calc(var(--rd-page) + 2 * var(--rd-margin, 22px) + 2px);
  margin-inline: auto;
}

[data-reading="scroll"] .rd-flow {
  max-width: var(--measure);
  margin-inline: auto;
}

/* Ab 900 steht links die Schiene: die Zielerinnerung gehört über den
   Inhalt, nicht über das Fenster. Ihre Unterkante rechnet mit
   --sh-tabs-h und rückt von selbst nach (styles/shell.css). */
@media (min-width: 900px) {
  body[data-shell] .rd-remind { inset-inline-start: calc(50% + var(--rail-w) / 2); }

  /* In der Lesesitzung gibt es keinen Einzug (siehe unten) – dann steht
     die Erinnerung auch wieder auf der Mitte des Bildschirms. */
  body.is-reader[data-shell] .rd-remind { inset-inline-start: 50%; }
}

/* Ab 900 ist der Lesebildschirm ein Blatt, kein Fenster.
   ------------------------------------------------------------------
   Die Seite hört bei --rd-page auf (siehe oben) – der Bildschirm
   drumherum tat es bisher nicht: Kopfzeile, Werkzeuge und
   Fortschrittszeile liegen absolut in .rd-read und spannten damit
   über die ganze Inhaltsbreite, während das Blatt in der Mitte
   stand. Zwei verschiedene Mitten in einem Bild.

   Also bekommt .rd-read dieselbe Grenze: Seite plus Rand plus die
   1px-Kante der Fläche. Alles, was darin absolut liegt, fluchtet
   dann mit der Seite.

   Die Rinne der Seite fällt dabei auf 8px – bei 936px Fensterbreite
   nehmen Schiene (128) und zwei Rinnen (2 x 32) sonst so viel weg,
   dass für das Blatt keine vollen 720 übrig blieben. Dann wäre die
   Seite bei 936 schmaler als bei 1280, und genau das soll sie nicht
   sein: die Seitenzahlen eines Buches hängen an ihrer Breite. Der
   Lesebildschirm braucht die Rinne ohnehin nicht – er bringt seinen
   eigenen Rand mit. */
@media (min-width: 900px) {
  body.is-reader .app { padding-inline: 8px; }

  /* ---------- Die Seite steht auf der Mitte des Bildschirms ----------------

     styles/shell.css rückt ab 900 die ganze Seite um die Schiene ein
     (`body[data-shell] { padding-inline-start: var(--rail-w) }`). Für jede andere
     Umgebung ist das richtig: die Schiene nimmt Platz weg, also bekommt
     der Inhalt weniger.

     Im Lesebildschirm nicht. Dort liegt die Schiene über dem Text statt
     neben ihm – wie die Kopfzeile des Buches und die Fortschrittszeile
     auch –, und der Einzug schob das Blatt um 64 Pixel nach rechts aus
     der Mitte des Bildschirms. Bei aufgedeckter Leiste stand es woanders
     als ohne, und im Vollbild stand es schief in einem Bild, in dem
     nichts anderes mehr war.

     Der Einzug fällt deshalb für die ganze Lesesitzung weg – nicht erst
     beim Verstecken der Leisten. `body.is-reader` sitzt vom Öffnen des
     Buches bis zum Verlassen des Bildschirms (openBook/destroy in
     app/reader/read.js) und wechselt dazwischen nie. Damit kann ein Tipp
     in die Mitte den Umbruch nicht bewegen: die Spaltenbreite ist
     während der ganzen Sitzung dieselbe, und die Seitenzahl bleibt
     stehen, wo sie stand. */
  body.is-reader[data-shell] { padding-inline-start: 0; }


  /* .mnt.rd-read, nicht nur .rd-read: die Ausnahmeliste in
     styles/components.css nimmt diesem Bildschirm die Flussgrenze
     mit derselben Doppelklasse wieder ab. */
  .mnt.rd-read {
    max-width: calc(var(--rd-page) + 2 * var(--rd-margin, 22px) + 2px);
    margin-inline: auto;
  }
}


/* =========================================================
   Am Rand weiterblättern: der Schimmer

   Während eine Auswahl am Rand der Fläche gehalten wird,
   glimmt die Kante auf, an der es gleich weitergeht. Es ist
   das Einzige, was davon zu sehen ist – ein Knopf wäre ein
   Knopf zu viel, und ohne Zeichen wirkte das Umblättern wie
   ein Versehen.

   Nur Deckkraft, keine Bewegung: darunter liegt Text, den
   jemand gerade liest.
   ========================================================= */

.rd-read::before,
.rd-read::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 64px;
  z-index: 5;
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms var(--ease-out);
}

.rd-read::before {
  inset-inline-start: 0;
  background: linear-gradient(to right, rgba(var(--t-reader), .34), transparent);
}

.rd-read::after {
  inset-inline-end: 0;
  background: linear-gradient(to left, rgba(var(--t-reader), .34), transparent);
}

.rd-read.is-edge-left::before,
.rd-read.is-edge-right::after { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .rd-read::before,
  .rd-read::after { transition: none; }
}

/* =========================================================
   Stimmen: der Weg dorthin

   Im Fenster des Vorlesers stehen nur noch die Stimmen, die
   auf dem Gerät liegen. Darunter dieser Weg – gestrichelt,
   weil dahinter etwas kommt, das erst geholt werden muss.
   ========================================================= */

.rd-tts-add {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 9px 12px;
  border-radius: 10px;
  border: 1px dashed var(--line-strong);
  background: transparent;
  color: var(--accent-app);
  font-size: 13px;
  text-align: start;
  transition: border-color var(--dur) var(--ease-out),
              background-color var(--dur) var(--ease-out);
}

.rd-tts-add:hover {
  border-style: solid;
  border-color: var(--accent-app);
  background: rgba(var(--t-reader), .1);
}

.rd-tts-add__plus,
.rd-voices-toggle__plus {
  position: relative;
  flex: none;
  width: 14px;
  height: 14px;
}

.rd-tts-add__plus::before,
.rd-tts-add__plus::after,
.rd-voices-toggle__plus::before,
.rd-voices-toggle__plus::after {
  content: "";
  position: absolute;
  border-radius: 1px;
  background: currentColor;
}

.rd-tts-add__plus::before,
.rd-voices-toggle__plus::before {
  inset-inline-start: 0;
  top: 6px;
  width: 14px;
  height: 2px;
}

.rd-tts-add__plus::after,
.rd-voices-toggle__plus::after {
  inset-inline-start: 6px;
  top: 0;
  width: 2px;
  height: 14px;
  transition: transform 200ms var(--ease-out);
}

/* =========================================================
   Der Bildschirm /reader/voices
   ========================================================= */

.rd-voices-lead { margin: 0 0 14px; }

.rd-voices .mnt-card__title small {
  font-size: max(var(--fs-floor), 10.5px);
  letter-spacing: 0;
  color: var(--text-dim);
}

.rd-voices-list {
  display: grid;
  gap: 8px;
}

.rd-voice {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 10px 9px 12px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--rd-line);
  transition: border-color var(--dur) var(--ease-out);
}

.rd-voice.is-on { border-color: var(--accent-app); }

.rd-voice__pick {
  flex: 1;
  display: grid;
  gap: 2px;
  min-width: 0;
  background: none;
  border: 0;
  padding: 0;
  text-align: start;
}

.rd-voice__name { font-size: 15px; color: var(--text); }
.rd-voice__hint { font-size: max(var(--fs-floor), 11.5px); color: var(--text-dim); }

/* Die laufende Stimme trägt den Akzent als Fläche – mit --ink darauf,
   dieselbe Paarung wie .rd-btn und .rd-tts-voice.is-on. Heller Text auf
   dem hellen Akzent käme nicht über 4,5:1. */
.rd-voice__now {
  flex: none;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--accent-app);
  color: var(--ink);
  font-size: max(var(--fs-floor), 10px);
  letter-spacing: .08em;
  text-transform: uppercase;
}

.rd-voice__btn {
  flex: none;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  border: 1px solid var(--rd-line);
  background: var(--g-47);
  color: var(--text-dim);
  transition: color var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out);
}

.rd-voice__btn:hover {
  color: var(--accent-app);
  border-color: var(--accent-app);
}

.rd-voice__btn:active { transform: scale(.94); }

.rd-voice__btn--drop:hover {
  color: #e2a3a3;
  border-color: #e2a3a3;
}

/* ---------- Die Schublade -------------------------------------------------- */

.rd-voices-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--rd-line);
  background: var(--g-47);
  color: var(--text);
  font-size: 14px;
  text-align: start;
}

.rd-voices-toggle:hover { border-color: var(--accent-app); }
.rd-voices-toggle__plus { color: var(--accent-app); }

/* Aufgeklappt wird aus dem Plus ein Minus – der Balken bleibt, der
   Strich fährt ein. */
.rd-voices-toggle.is-open .rd-voices-toggle__plus::after { transform: scaleY(0); }

.rd-voices-drawer {
  display: grid;
  gap: 10px;
  margin-top: 10px;
  padding: 12px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--rd-line);
}

.rd-offers {
  display: grid;
  gap: 8px;
}

.rd-offer {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--g-47);
  border: 1px solid transparent;
}

/* Was schon da ist, tritt zurück – aber über die Farbe, nicht über die
   Deckkraft. Ein opacity auf der ganzen Zeile zog auch die Auskunft
   rechts mit hinunter, und die muss lesbar bleiben. */
.rd-offer.is-here { background: transparent; border-color: var(--rd-line); }
.rd-offer.is-here .rd-offer__name { color: var(--text-dim); }

.rd-offer__body {
  flex: 1;
  display: grid;
  gap: 3px;
  min-width: 0;
}

.rd-offer__name { font-size: 14.5px; color: var(--text); }
.rd-offer__hint { font-size: max(var(--fs-floor), 11px); color: var(--text-dim); }
.rd-offer__err  { font-size: max(var(--fs-floor), 11px); color: #e2a3a3; }

.rd-offer__bar {
  display: block;
  height: 4px;
  margin-top: 3px;
  border-radius: 2px;
  background: var(--rd-line);
  overflow: hidden;
}

.rd-offer__bar[hidden] { display: none; }

.rd-offer__bar i {
  display: block;
  height: 100%;
  background: var(--accent-app);
  transition: width 120ms linear;
}

.rd-offer__go {
  flex: none;
  min-width: 106px;
  text-align: center;
}

/* Der Stand einer Stimme: „On device" oder „42 %". Kein Knopf – da ist
   nichts mehr zu drücken. Rechtsbündig auf derselben Breite wie der
   Knopf, damit die Spalte beim Wechsel nicht springt. */
.rd-offer__state {
  flex: none;
  min-width: 106px;
  text-align: center;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--accent-app);
}

.rd-offer__state.is-here { color: var(--text-dim); }


/* =========================================================
   TEIL 3 – Die Formensprache, nachgezogen

   Der Reader war der letzte grosse Bereich in der alten
   Sprache: 108 Radien, davon vierzehn volle Pillen (999px)
   und vierzehn Kreise (50 %), eine gequetschte Ellipse als
   Auge – und kein einziger Sockel. Gedrueckt schrumpften die
   Knoepfe auf 92–96 %, was in keiner Oberflaeche der Welt
   etwas bedeutet.

   Die Regel, in einem Satz:

     Flaechen bekommen zwei geschnittene Ecken – oben links
     und unten rechts, immer dieselbe Diagonale. Knoepfe sind
     rechte Winkel mit einem Sockel dahinter und sinken beim
     Druck um genau die Sockeltiefe ein. Nichts ist rund.

     Unter etwa 30px mit einem Zeichen darin entfaellt der
     Schnitt – die Diagonale fuehre sonst durch das Zeichen.
     Ein Rechteck ist immer noch nicht rund.

   Wo die Grenze zwischen beiden liegt:

     Ein Knopf ist ein BEDIENELEMENT – Zeichen, Handlung,
     Auswahl, Schalter. Eine Flaeche ist INHALT, auch wenn
     sie sich anfassen laesst: eine Zeile in der Buchliste,
     eine Markierung im Annotations-Reiter, ein Segment eines
     Schalters. Deshalb ist .rn-row eine Flaeche und .rn-jump
     ein Knopf, obwohl beide <button> sind. Sonst truege jede
     Liste dieses Bereichs dreissig Sockel.

     Und der Lesebildschirm selbst ist die Ausnahme, die die
     Regel bestaetigt: .rd-stage traegt KEINEN Schnitt. Eine
     Diagonale durch die Ecke einer Textspalte schneidet
     Woerter ab. Ein Rechteck ist dort die Form, nicht der
     Verzicht auf eine.

   Warum das hier unten steht und nicht oben bei den
   Bausteinen selbst: gleiche Spezifitaet, spaetere Regel
   gewinnt. So steht die Entscheidung je Baustein an EINER
   Stelle und ist nachlesbar, statt ueber 3 200 Zeilen
   verteilt zu sein.

   Dieselben drei Fallen wie in Nutrition und Fitness:
     - clip-path schneidet border UND box-shadow mit weg. Ein
       Zustand, der auf einem Rand lag, wandert in die Flaeche
       oder wird zum inneren Schatten.
     - z-index:-1-Pseudoelemente brauchen isolation:isolate.
     - Jeder Sockel braucht eine E-ink-Fassung – siehe unten.
   ========================================================= */

/* ---------- Knoepfe: rechter Winkel, Sockel dahinter ---------------------- */

.rd-btn,
.rd-mini,
.rd-iconbtn,
.lib-round,
.lib-shelf__more,
.lib-next,
.lib-tile__menu,
.lib-sheet__cancel,
.rd-join__btn,
.rd-chip,
.rd-tool,
.rd-font,
.rd-series__next,
.rd-tile__menu,
.ra-act,
.ra-color,
.rn-block__fold,
.rn-block__act,
.rn-jump,
.rd-voice__btn,
.rd-tts-add,
.rd-voices-toggle,
.rd-check__box {
  --depth: 2.5px;
  --btn-face: var(--btn-quiet);
  --btn-face-hover: var(--btn-quiet-hover);
  --btn-lift: var(--btn-quiet-lift);

  position: relative;
  isolation: isolate;
  border: 0;
  border-radius: 0;
  background: none;
  transition: transform var(--dur-fast) var(--ease-out);
}

:is(.rd-btn, .rd-mini, .rd-iconbtn, .lib-round, .lib-shelf__more, .lib-next,
    .lib-tile__menu, .lib-sheet__cancel, .rd-join__btn, .rd-chip, .rd-tool,
    .rd-font, .rd-series__next, .rd-tile__menu, .ra-act, .ra-color,
    .rn-block__fold, .rn-block__act, .rn-jump, .rd-voice__btn, .rd-tts-add,
    .rd-voices-toggle, .rd-check__box)::before,
:is(.rd-btn, .rd-mini, .rd-iconbtn, .lib-round, .lib-shelf__more, .lib-next,
    .lib-tile__menu, .lib-sheet__cancel, .rd-join__btn, .rd-chip, .rd-tool,
    .rd-font, .rd-series__next, .rd-tile__menu, .ra-act, .ra-color,
    .rn-block__fold, .rn-block__act, .rn-jump, .rd-voice__btn, .rd-tts-add,
    .rd-voices-toggle, .rd-check__box)::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  /* KEIN clip-path. Ein Rechteck mit geschnittenen Ecken ist ein
     Sechseck – und Sechsecke sind in dieser App Flaechen, nicht
     Knoepfe. Der Schnitt hier waere genau der Fehler, den die ganze
     Unterscheidung verhindern soll. */
}

:is(.rd-btn, .rd-mini, .rd-iconbtn, .lib-round, .lib-shelf__more, .lib-next,
    .lib-tile__menu, .lib-sheet__cancel, .rd-join__btn, .rd-chip, .rd-tool,
    .rd-font, .rd-series__next, .rd-tile__menu, .ra-act, .ra-color,
    .rn-block__fold, .rn-block__act, .rn-jump, .rd-voice__btn, .rd-tts-add,
    .rd-voices-toggle, .rd-check__box)::before {
  background: var(--btn-lift);
  transform: translate(var(--depth), var(--depth));
  transition: opacity var(--dur-fast) var(--ease-out);
}

:is(.rd-btn, .rd-mini, .rd-iconbtn, .lib-round, .lib-shelf__more, .lib-next,
    .lib-tile__menu, .lib-sheet__cancel, .rd-join__btn, .rd-chip, .rd-tool,
    .rd-font, .rd-series__next, .rd-tile__menu, .ra-act, .ra-color,
    .rn-block__fold, .rn-block__act, .rn-jump, .rd-voice__btn, .rd-tts-add,
    .rd-voices-toggle, .rd-check__box)::after {
  background-image: linear-gradient(var(--btn-face), var(--btn-face));
  background-color: var(--btn-under, var(--surface));
  transition: background-color var(--dur) var(--ease-out);
}

/* Die alten Zustaende lagen auf `background` und `filter` des Knopfes
   selbst – beides liegt jetzt in der Flaeche dahinter, sonst deckte
   die alte Farbe den ganzen Bau zu. */
:is(.rd-btn, .rd-mini, .rd-iconbtn, .lib-round, .lib-shelf__more, .lib-next,
    .lib-tile__menu, .lib-sheet__cancel, .rd-join__btn, .rd-chip, .rd-tool,
    .rd-font, .rd-series__next, .rd-tile__menu, .ra-act, .ra-color,
    .rn-block__fold, .rn-block__act, .rn-jump, .rd-voice__btn, .rd-tts-add,
    .rd-voices-toggle, .rd-check__box):hover { background: none; filter: none; }

:is(.rd-btn, .rd-mini, .rd-iconbtn, .lib-round, .lib-shelf__more, .lib-next,
    .lib-tile__menu, .lib-sheet__cancel, .rd-join__btn, .rd-chip, .rd-tool,
    .rd-font, .rd-series__next, .rd-tile__menu, .ra-act, .ra-color,
    .rn-block__fold, .rn-block__act, .rn-jump, .rd-voice__btn, .rd-tts-add,
    .rd-voices-toggle, .rd-check__box):hover::after {
  background: var(--btn-face-hover);
}

/* Eingedrueckt: der Knopf wandert auf den Sockel, der Sockel geht weg.
   Ein Knopf, der beim Druck nicht sichtbar einsinkt, ist ein
   Aufkleber. Vorher schrumpften sie auf 92–96 %. */
:is(.rd-btn, .rd-mini, .rd-iconbtn, .lib-round, .lib-shelf__more, .lib-next,
    .lib-tile__menu, .lib-sheet__cancel, .rd-join__btn, .rd-chip, .rd-tool,
    .rd-font, .rd-series__next, .rd-tile__menu, .ra-act, .ra-color,
    .rn-block__fold, .rn-block__act, .rn-jump, .rd-voice__btn, .rd-tts-add,
    .rd-voices-toggle, .rd-check__box):active {
  transform: translate(var(--depth), var(--depth));
}

:is(.rd-btn, .rd-mini, .rd-iconbtn, .lib-round, .lib-shelf__more, .lib-next,
    .lib-tile__menu, .lib-sheet__cancel, .rd-join__btn, .rd-chip, .rd-tool,
    .rd-font, .rd-series__next, .rd-tile__menu, .ra-act, .ra-color,
    .rn-block__fold, .rn-block__act, .rn-jump, .rd-voice__btn, .rd-tts-add,
    .rd-voices-toggle, .rd-check__box):active::before { opacity: 0; }

/* --- Sorte 1: Zeichen ohne eigene Flaeche --------------------------------
   Ein Sockel hinter einer durchsichtigen Flaeche scheint auf voller
   Groesse durch und macht aus dem Knopf einen Block. Diese hier tragen
   ihn deshalb erst, wenn es auch eine Flaeche gibt, die ihn deckt. */
:is(.rn-block__fold, .rn-block__act, .lib-shelf__more, .rn-jump,
    .ra-color, .rd-mini, .rd-tile__menu)::before { opacity: 0; }

:is(.rn-block__fold, .rn-block__act, .lib-shelf__more, .rn-jump,
    .ra-color, .rd-mini, .rd-tile__menu):hover::before,
:is(.rn-block__fold, .rn-block__act, .lib-shelf__more, .rn-jump,
    .ra-color, .rd-mini, .rd-tile__menu):focus-visible::before { opacity: 1; }

/* --- Sorte 2: getoente Flaechen brauchen eine deckende Unterlage ---------
   background-image traegt den Ton, background-color die Deckung. So
   bleibt --btn-face genau der Wert, der ueberall sonst gesetzt wird. */
:is(.lib-next, .rd-series__next, .rd-tool, .ra-act, .rd-chip, .rd-join__btn,
    .lib-round, .rd-iconbtn, .rd-voices-toggle, .rd-tts-add)::after {
  background-image: linear-gradient(var(--btn-face), var(--btn-face));
  background-color: var(--btn-under, var(--surface));
}

/* --- Die Flaechen und Tiefen je Knopf ------------------------------------ */

/* Der handelnde Knopf: Akzentflaeche, dunkler Sockel, dunkle Schrift.
   ------------------------------------------------------------------
   WELCHES Braun die Flaeche traegt, ist hier keine Geschmacksfrage,
   sondern eine Rechnung. Gemessen gegen --on-accent (#0f1114):

     --accent-deep  #86664b   3,62:1   faellt durch
     --accent-app   #b08968   5,96:1   haelt AA
     app + 18% Weiss          7,79:1   haelt AA auch beim Ueberfahren

   Fitness setzt die Flaeche auf --accent-deep und den Zeiger-Zustand
   auf --accent-app. Das geht dort auf, weil das Korall dieses Bereichs
   heller ist als dieses Braun. Uebernimmt man die Zeilen unbesehen,
   steht dunkle Schrift auf 3,62:1 – und genau das stand hier einen
   Durchgang lang. Der Reader dreht das Paar deshalb um: die HELLE
   Fassung traegt die Schrift, die dunkle wird der Sockel.

   13px halbfett ist keine "grosse Schrift" im Sinne der Richtlinie
   (dafuer braeuchte es 18,66px fett), 4,5:1 gilt also voll. */
.rd-btn {
  --btn-face: var(--accent-app);
  --btn-face-hover: color-mix(in srgb, var(--accent-app) 82%, #ffffff);
  --btn-lift: var(--accent-deep);
  color: var(--on-accent);
  font-weight: 600;
}

.rd-btn img { filter: none; }

/* Der zweite Knopf der Karte: dieselbe Form, ruhigere Flaeche. Zwei
   Akzentknoepfe nebeneinander haetten keine Rangfolge mehr. Der Rand,
   der ihn vorher auszeichnete, ist weg – er lag auf einem border und
   haette den Sockel ueberstimmt. */
.rd-btn--ghost {
  --btn-face: var(--tint-face);
  --btn-face-hover: var(--tint-hover); --btn-lift: var(--tint-lift);
  color: var(--accent-app);
  font-weight: 500;
}

.rd-btn--ghost.is-on {
  --btn-face: var(--accent-app);
  --btn-face-hover: color-mix(in srgb, var(--accent-app) 82%, #ffffff);
  --btn-lift: var(--accent-deep);
  color: var(--on-accent);
  font-weight: 600;
}

.rd-btn--danger {
  --btn-face: rgba(var(--t-fitness-stroke), .16);
  --btn-face-hover: rgba(var(--t-fitness-stroke), .26);
  --btn-lift: #3a1f1f;
  color: #ffb3b3;
  font-weight: 600;
}

/* Abgeschaltet heisst: kein Sockel, keine Bewegung. WCAG nimmt
   abgeschaltete Bedienelemente vom Kontrastminimum aus. */
:is(.rd-btn, .rd-mini, .rd-iconbtn, .rd-voice__btn, .rd-tts-add)[disabled]::before {
  opacity: 0;
}

:is(.rd-btn, .rd-mini, .rd-iconbtn, .rd-voice__btn, .rd-tts-add)[disabled]:active {
  transform: none;
}

.rd-mini {
  --depth: 2px;
  --btn-face: var(--btn-quiet);
  --btn-face-hover: var(--tint-hover); --btn-lift: var(--tint-lift);
  color: var(--text-dim);
}

.rd-mini:hover { color: var(--accent-app); }

/* Das Zeichen im Kasten. Sein Zustand lag auf border-color und haette
   den Sockel nicht ueberlebt – er liegt jetzt in der Flaeche. */
.rd-iconbtn {
  --btn-face: var(--tint-face);
  --btn-face-hover: var(--tint-hover);
  --btn-lift: var(--tint-lift);
  --btn-edge: var(--tint-edge);
  --btn-under: var(--bg);
  color: var(--tint-ink);
  filter: var(--tint-glow);
}

.rd-iconbtn::after,
.lib-round::after { box-shadow: inset 0 0 0 1.5px var(--btn-edge, transparent); }

.rd-iconbtn.is-on {
  --btn-face: rgba(var(--t-reader), var(--btn-tint-on-a));
  --btn-face-hover: var(--tint-hover); --btn-lift: var(--tint-lift);
}

.lib-round {
  --btn-face: var(--tint-face);
  --btn-face-hover: var(--tint-hover);
  --btn-lift: var(--tint-lift);
  --btn-edge: var(--tint-edge);
  --btn-under: var(--bg);
  color: var(--tint-ink);
  filter: var(--tint-glow);
}

.lib-round.is-on {
  --btn-face: rgba(var(--t-reader), var(--btn-tint-on-a));
  --btn-face-hover: var(--tint-hover); --btn-lift: var(--tint-lift);
}

.lib-round--accent {
  --btn-edge: transparent;
  --btn-face: var(--accent-app);
  --btn-face-hover: color-mix(in srgb, var(--accent-app) 82%, #ffffff);
  --btn-lift: var(--accent-deep);
  --btn-lift: #4a3524;
}

.lib-round--accent:hover { filter: none; }
.lib-round--accent img { filter: none; }

.lib-shelf__more { --depth: 2px; }

/* ---------- Der Dreipunkt auf einer Buchkachel --------------------------
   Zwei Sachen auf einmal, und die erste ist eine Reparatur.

   1. Er sass in der Ecke des Covers, mit `position: absolute`. Der
      gemeinsame Bauplan der Knoepfe weiter oben setzt aber
      `position: relative` – der Sockel braucht einen Bezugsrahmen –,
      und weil er spaeter steht und gleich spezifisch ist, gewann er.
      Der Knopf fiel damit aus der Ecke in den normalen Fluss und
      stand unter der Kachel. `absolute` ist selbst ein Bezugsrahmen,
      der Sockel bleibt also heil; es muss nur wieder dastehen.

   2. Er liegt auf dem Cover, und das Cover oeffnet das Buch. Wer den
      Punkt knapp verfehlte, landete im Buch statt im Menue – und der
      Weg zurueck ist eine ganze Lesesitzung. Also bekommt er einen
      Graben: die Trefferflaeche ist 42px, zu sehen sind davon 26px in
      der Mitte. Die 8px ringsum fangen den knappen Daumen ab und tun
      sonst nichts – sie oeffnen weder Buch noch Menue.

   Gerechnet: 42 - 2 x 8 = 26, und -3 + 8 = 5. Flaeche und Abstand zur
   Kante sind damit auf den Pixel dieselben wie vorher, nur der
   Einzugsbereich ist groesser. */
.lib-tile__menu {
  --depth: 2px;
  --btn-face: rgba(var(--o-bg), .55);
  --btn-face-hover: rgba(var(--o-bg), .75);
  /* Bleibt Glas: der Knopf liegt auf einem Buchcover, seine Fläche ist
     der Schleier davor. Eine deckende Unterlage nähme ihm den Blick
     aufs Cover und damit den Sinn. */
  --btn-under: transparent;

  position: absolute;
  top: -3px;
  inset-inline-end: -3px;
  width: 42px;
  height: 42px;
}

/* Der Sockel und die Flaeche fuellen NICHT den ganzen Knopf – sie
   sitzen in der Mitte, und der Rest ist der Graben. */
.lib-tile__menu::before,
.lib-tile__menu::after { inset: 8px; }

/* Die Unschaerfe gehoert zur sichtbaren Flaeche, nicht zur
   Trefferflaeche: auf dem Knopf selbst waere ein verwaschenes Quadrat
   von 42px zu sehen, wo nur 26px etwas zeigen sollen. */
.lib-tile__menu { backdrop-filter: none; }
.lib-tile__menu::after { backdrop-filter: blur(6px); }

/* Dieselbe Reparatur an der alten Kachel. */
.rd-tile__menu {
  --depth: 2px;
  --btn-under: transparent;   /* Glas über dem Cover – siehe .lib-tile__menu */
  position: absolute;
  top: -3px;
  inset-inline-end: -3px;
  width: 44px;
  height: 44px;
}

.rd-tile__menu::before,
.rd-tile__menu::after { inset: 7px; }

.rd-tile__menu { backdrop-filter: none; }
.rd-tile__menu::after { backdrop-filter: blur(3px); }

.lib-next,
.rd-series__next {
  --btn-face: var(--tint-face);
  --btn-face-hover: var(--tint-hover); --btn-lift: var(--tint-lift);
  color: var(--accent-app);
}

.lib-sheet__cancel {
  --btn-face: var(--btn-quiet);
  --btn-face-hover: var(--btn-quiet-hover);
  color: var(--text);
}

/* Auswahl-Chips und das UND/ODER: der Zustand sass auf einem Rand.
   Jetzt traegt ihn die Flaeche, und ausgewaehlt heisst Akzent. */
.rd-chip,
.rd-join__btn {
  --depth: 2px;
  --btn-face: var(--btn-quiet);
  --btn-face-hover: var(--btn-quiet-hover);
  color: var(--text-dim);
}

.rd-chip.is-on,
.rd-join__btn.is-on {
  --btn-face: var(--accent-app);
  --btn-face-hover: color-mix(in srgb, var(--accent-app) 82%, #ffffff);
  --btn-lift: var(--accent-deep);
  color: var(--on-accent);
  font-weight: 600;
}

.rd-tool {
  --depth: 2px;
  --btn-face: color-mix(in srgb, var(--accent-deep) 26%, transparent);
  --btn-face-hover: var(--accent-app);
  color: var(--accent-app);
}

.rd-tool:hover { color: var(--on-accent); }

.rd-font {
  --depth: 2px;
  --btn-face: var(--g-47);
  --btn-face-hover: var(--g-42);
}

.rd-font.is-on {
  --btn-face: color-mix(in srgb, var(--accent-deep) 34%, var(--g-47));
  --btn-face-hover: var(--btn-face);
}

/* Der Balken ueber einer Markierung. Die Handlungen sind Knoepfe, die
   Farben auch – nur klein genug, dass der Schnitt entfaellt. */
.ra-act {
  --depth: 2px;
  --btn-face: var(--btn-quiet);
  --btn-face-hover: var(--btn-quiet-hover);
  --btn-under: var(--surface-2);
}

.ra-act.is-on {
  --btn-face: var(--accent-app);
  --btn-face-hover: color-mix(in srgb, var(--accent-app) 82%, #ffffff);
  --btn-lift: var(--accent-deep);
  color: var(--on-accent);
}

.ra-act--danger {
  --btn-face-hover: rgba(var(--t-fitness-stroke), .26);
  color: #ff9a9a;
}

/* 30px, rechte Winkel, Sockel nur beim Ueberfahren: ein Sockel hinter
   einer nackten Farbe waere ein Schatten. Ausgewaehlt zeigt ein
   innerer Rahmen in der Grundfarbe – ein aeusserer Ring waere rund,
   und ein border stuende ueber dem Sockel. */
.ra-color {
  --depth: 2px;
  --btn-lift: #000000;
  --btn-under: var(--surface-2);
  width: 30px;
  height: 30px;
  border: 0;
}

/* Der Farbton kommt aus --btn-face (siehe colorRow in
   app/reader/annotate.js) und wird deshalb hier gedeckt aufgetragen:
   ein eigener `background` auf dem Knopf liegt UNTER seiner Flaeche
   und war unsichtbar – alle fuenf Marken sahen gleich grau aus. */
.ra-color::after {
  background-image: linear-gradient(var(--btn-face), var(--btn-face));
  background-color: var(--btn-under);
}

/* Ausgewaehlt: ein innerer Rahmen in der Flaeche selbst, nicht auf dem
   Knopf – auf dem Knopf laege er unter der Farbe. */
/* Gewaehlt: ein Rahmen um die Marke, mit Luft dazwischen. Ein Ring
   INNEN frisst von der Farbe, die er zeigen soll, und war bei 30px
   kaum zu sehen; ein Rahmen aussen laesst die Flaeche ganz und ist
   auf einen Blick da. Rechtwinklig, wie jeder Knopf hier. */
.ra-color.is-on {
  outline: 2px solid var(--g-01);
  outline-offset: 2px;
}

.rn-block__fold,
.rn-block__act { --depth: 2px; }

/* "Show in book" war ein unterstrichener Text und sah damit aus wie
   ein Verweis, obwohl er der Weg ins Buch ist – die Handlung dieser
   Karte. Als Knopf braucht er eine Flaeche, und eine Flaeche braucht
   ein Polster; die Unterstreichung faellt dafuer weg. */
.rn-jump {
  --btn-face: var(--tint-face);
  --btn-face-hover: var(--tint-hover); --btn-lift: var(--tint-lift);
  padding: 7px 12px;
  color: var(--accent-app);
  text-decoration: none;
  font-weight: 500;
  justify-self: start;
}

.rd-voice__btn {
  --depth: 2px;
  --btn-face: var(--g-47);
  --btn-face-hover: var(--g-42);
  color: var(--text-dim);
}

/* Der gestrichelte Rand sagte "hier ist noch nichts". Ein Sockel sagt
   dasselbe deutlicher, und er ueberlebt den Druck. */
.rd-tts-add {
  --btn-face: var(--tint-face);
  --btn-face-hover: var(--tint-hover); --btn-lift: var(--tint-lift);
  color: var(--accent-app);
}

.rd-voices-toggle {
  --btn-face: var(--g-47);
  --btn-face-hover: var(--g-42);
  color: var(--text);
}

/* Das Kaestchen einer Auswahl. Der Rand lag auf border und ist damit
   in die Flaeche gewandert; angehakt traegt es den Akzent. */
.rd-check__box {
  --depth: 2px;
  --btn-face: var(--g-47);
  --btn-face-hover: var(--g-42);
  box-shadow: inset 0 0 0 2px var(--line-strong);
}

.rd-check input:checked + .rd-check__box {
  --btn-face: var(--accent-app);
  --btn-face-hover: color-mix(in srgb, var(--accent-app) 82%, #ffffff);
  --btn-lift: var(--accent-deep);
  box-shadow: inset 0 0 0 2px var(--accent-deep);
}


/* ---------- Flaechen: zwei geschnittene Ecken ----------------------------- */

.rd-input,
.rd-warn,
.rd-seg,
.rd-blank,
.rd-foot,
.rd-tocrow,
.rd-optrow,
.rd-zp__page,
.rd-form__cover,
.rd-series,
.rd-tile__open,
.rd-info__stats,
.rd-info__desc,
.rd-info__meta,
.rd-tip,
.rd-remind,
.rd-offer,
.rd-tts-voice,
.rd-tts-stat,
.rd-voice,
.rd-voices-drawer,
.lib-search input,
.lib-sheet__rows,
.lib-tile__open,
.lib-folder__mini,
.lib-folder__empty,
.lib-folder__more,
.ra-pop,
.rn-row,
.rn-block,
.rn-note,
.rn-simple,
.rn-child,
.rn-rail,
.rn-card__face {
  --cut: 10px;
  border: 0;
  border-radius: 0;
  clip-path: var(--cut-clip);
}

/* Die groesseren Flaechen tragen einen groesseren Schnitt – sonst
   verschwindet die Diagonale in der Kante. */
.rd-blank,
.rd-foot,
.rd-series,
.rd-remind,
.rd-offer,
.rn-block,
.rn-card__face,
.rd-voice,
.rd-voices-drawer,
.lib-tile__open,
.lib-sheet__rows { --cut: 14px; }

/* Die Konturen, die auf einem `border` lagen: ein Rand ueberlebt
   clip-path nicht – er bricht auf beiden Diagonalen ab und laesst
   farbige Splitter stehen. Als innerer Schatten wird er mit der
   Flaeche zusammen geschnitten und folgt der Silhouette. */
.rd-input { box-shadow: inset 0 0 0 1.5px rgba(var(--o), .12); }
.rd-input:focus { box-shadow: inset 0 0 0 2px var(--accent-app); }

/* Der leere Zustand trug einen GESTRICHELTEN Rand – "hier ist noch
   nichts, hier koennte etwas sein". Gestrichelt kann ein innerer
   Schatten nicht, und der Rand selbst ueberlebt den Schnitt nicht.
   Also uebernimmt die Flaeche die Aussage: eine Spur heller als der
   Grund, mit einer durchgezogenen inneren Linie. Ein Behaelter bleibt
   es damit, ohne so zu tun, als waere er gefuellt. */
.rd-blank {
  background: rgba(var(--o), .03);
  box-shadow: inset 0 0 0 1.5px var(--line-strong);
}
.rd-warn { box-shadow: inset 0 0 0 1.5px rgba(var(--t-fitness-stroke), .45); }
.lib-search input { box-shadow: inset 0 0 0 1.5px rgba(var(--o), .12); }
.lib-search input:focus { box-shadow: inset 0 0 0 2px var(--accent-app); }

.rd-voice,
.rd-voices-drawer,
.rd-tts-voice { box-shadow: inset 0 0 0 1px var(--rd-line); }

/* Die schwebenden Flaechen. Ihr Schlagschatten faellt mit dem Schnitt
   weg – clip-path schneidet die ganze Darstellung, den Schatten
   eingeschlossen. Was sie abhebt, ist deshalb jetzt die Kontur nach
   innen: beim Balken und beim Banner in Akzent, weil sie ueber dem
   Buchtext liegen und sich von ihm loesen muessen. */
.ra-pop { box-shadow: inset 0 0 0 1.5px var(--accent-deep); }
.rd-tip { box-shadow: inset 0 0 0 1px var(--rd-line); }
.rd-remind { box-shadow: inset 0 0 0 1.5px var(--c-reader-stroke); }

/* Der Rahmen eines Blocks WAR seine Aussage: hier haelt etwas
   zusammen. 1,5px Akzent, jetzt innen, damit er der geschnittenen
   Ecke folgt statt an ihr abzubrechen. */
.rn-block { box-shadow: inset 0 0 0 1.5px var(--accent-deep); }

.rn-card__face,
.rd-series,
.rd-form__cover,
.rd-tts-stat { box-shadow: inset 0 0 0 1px var(--rd-line); }

.rd-zp__page { box-shadow: inset 0 0 0 1.5px var(--line-strong); }

/* Die Zitate: der farbige Strich links WAR ihr Kennzeichen und ist es
   weiter – nur als innerer Schatten, der die geschnittene Ecke
   mitnimmt, statt oben und unten darueber hinauszulaufen. */
.ra-quote,
.rn-quote,
.rn-passage {
  --cut: 10px;
  border: 0;
  border-radius: 0;
  clip-path: var(--cut-clip);
}

.ra-quote,
.rn-quote { box-shadow: inset 3px 0 0 var(--mark, var(--accent-app)); }
.rn-passage { box-shadow: inset 3px 0 0 var(--accent-deep); }

/* Ein Segment SCHALTET UM, es handelt nicht – also kein Sockel. Und
   keinen eigenen Schnitt: den traegt der Rahmen darum, sonst stuenden
   drei Sechsecke in einem Sechseck. */
.rd-seg__btn {
  border: 0;
  border-radius: 0;
  background: none;
}

.rd-seg__btn:hover { background: rgba(var(--o), .05); }

/* Dieselbe Rechnung wie beim handelnden Knopf (siehe .rd-btn oben):
   das gewaehlte Segment traegt die HELLE Fassung, sonst stuende die
   dunkle Schrift auf 3,62:1. */
.rd-seg__btn.is-on {
  background: var(--accent-app);
  color: var(--on-accent);
  font-weight: 600;
}

/* Zeilen bleiben Zeilen: Eckschnitt, kein Sockel, und kein transform
   beim Druck – eine Zeile, die schrumpft, sieht aus wie ein Fehler.
   Sie wird heller, das genuegt. */
:is(.rn-row, .rn-simple, .rd-tocrow, .rd-optrow):active {
  transform: none;
  background: var(--g-42);
}

/* Das Cover ist eine Abbildung, kein Knopf – auch wenn man es
   antippt, um das Buch zu oeffnen. Es schrumpfte beim Druck auf 97 %,
   und ein Buchdeckel, der kleiner wird, wenn man ihn anfasst, ist
   dieselbe leere Geste wie ein Knopf ohne Sockel. Rueckmeldung gibt
   stattdessen die Flaeche: sie wird kurz dunkler, so wie ein Blatt
   unter einem Finger. Nicht ueber .lib-tile__shade – der Schleier hat
   keine eigene Deckkraft, ihn abzusenken machte ihn HELLER. */
.lib-tile__open:active,
.rd-tile__open:active {
  transform: none;
  filter: brightness(.86);
}

/* Das Blatt selbst: rechte Winkel, kein Schnitt. Eine Diagonale durch
   die Ecke einer Textspalte schneidet Woerter ab – und der Rand bleibt
   ein echter `border`, weil app/reader/read.js seine zwei Pixel in die
   Seitenbreite einrechnet (MAX_PAGE, siehe .rd-stage weiter oben). */
.rd-stage {
  border-radius: 0;
  clip-path: none;
}

/* Bilder und PDF-Seiten sind Abbildungen, keine Flaechen der App –
   sie bleiben rechteckig, wie das Original. */
.rd-flow img,
.rd-flow svg,
.rd-pdfpage {
  border-radius: 0;
  clip-path: none;
}

/* Die Tippflaechen liegen ueber dem Text. Ein Schnitt an ihrer Ecke
   sieht aus wie ein Riss in der Seite, ein Radius wie eine Karte, die
   dort nicht hingehoert. Ein Rechteck zeigt eine Flaeche. */
.rd-zone { border-radius: 0; clip-path: none; }

/* Die Karte im Review-Modus dreht sich um ihre Achse. Geschnitten
   werden die beiden Seiten (.rn-card__face), nicht der Rahmen darum –
   ein clip-path auf einem Element mit transform-style: preserve-3d
   flacht die Drehung ein. */
.rn-card,
.rn-card__inner { border-radius: 0; }


/* ---------- Rechteckig, ohne Schnitt (unter der Schwelle) ----------------- */

/* Marken, Zaehler, Striche und Balken: unter etwa 30px fuehrt die
   Diagonale durch das Zeichen selbst. Rechteckig – aber nicht rund. */
.rd-iconbtn__dot,
.lib-search__icon,
.lib-crumb__count,
.lib-shelf__count,
.lib-shelf__more::before,
.lib-tile__badge,
.lib-tile__menu span,
.lib-sheet__grip,
.rd-tile__badge,
.rd-legend i,
.rd-bar__fill,
.rd-split__track,
.rd-heat__cell,
.rd-foot__bar,
.rd-foot__goal,
.rd-offer__bar,
.rd-tts-line,
.rd-voice__now,
.rd-voices-toggle__plus::after,
.rd-optrow__mark,
.rd-noannot__mark::before,
.rd-noannot__mark::after,
.ra,
.ra-cx--start,
.ra-cx--end,
.rn-row__cover,
.rn-row__count,
.rn-block__count,
.rn-rail__dash,
.rn-kind,
.rn-simple__dot,
.rd-remind button {
  border-radius: 0;
}

/* Zwei Marken trugen dunkle Schrift auf --accent-deep und fielen damit
   durch dieselbe Rechnung wie der Knopf oben: 3,62:1 bei 8,5px und
   10px halbfett. Die helle Fassung bringt sie auf 5,96:1. Ein Wort in
   Grossbuchstaben von acht Pixeln ist die kleinste Schrift des
   Bereichs – sie braucht den Abstand am meisten. */
.rn-kind--complex {
  background: var(--accent-app);
  color: var(--on-accent);
}

/* Das Sheet sitzt auf der Bildschirmkante: oben eine geschnittene
   Ecke, unten keine – die untere Kante laeuft durch. */
.rd-pop--sheet {
  border-radius: 0;
  clip-path: polygon(14px 0, 100% 0, 100% 100%, 0 100%, 0 14px);
}


/* ---------- Sechsecke: was rund bleiben WOLLTE ---------------------------- */

/* Der Zielring stand an drei Stellen als Kreis: in der Fortschritts-
   zeile, im Erinnerungsbanner und als grosse Fassung in den Stats.
   Der Sweep bleibt ein conic-gradient – nur die Silhouette ist jetzt
   die der App. Statt der radialen Maske schneidet ein zweites
   Sechseck das Loch, sonst waere der Ring innen rund. */
.rd-goalring {
  position: relative;
  isolation: isolate;
  border-radius: 0;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  mask: none;
  -webkit-mask: none;
}

.rd-goalring::before {
  content: "";
  position: absolute;
  inset: 24%;
  background: var(--bg);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

/* Im grossen Ring steht die Zahl, und die Mitte macht dort ::after –
   ein zweites Loch waere eins zu viel. */
.rd-goalring--lg { border-radius: 0; }
.rd-goalring--lg::before { display: none; }

.rd-goalring--lg::after {
  border-radius: 0;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

/* Die Ziehpunkte an den Enden einer Markierung. Ein Kreis war die
   Anleihe beim System; ein Sechseck ist die Form dieser App und
   trifft den Finger genauso. Der weisse Rand lag auf border und
   ueberlebt den Schnitt nicht – die Flaeche traegt ihn selbst. */
.ra-grip {
  border: 0;
  border-radius: 0;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  box-shadow: none;
}

/* Der Wartekreis. Ein rotierender Rand ueberlebt den Schnitt nicht –
   also dreht sich ein Sechseck mit einem Farbverlauf darin. Dieselbe
   Aussage, dieselbe Dauer, die Form der App. */
.rd-wait__spin {
  border: 0;
  border-radius: 0;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  background: conic-gradient(var(--accent-app) 0deg,
                             rgba(var(--o), .18) 250deg,
                             rgba(var(--o), .18) 360deg);
}

/* Das Auge des Guck-Modus war eine Ellipse mit einem Kreis darin –
   die einzige gequetschte Rundung der ganzen App. Jetzt: ein flaches
   Sechseck als Lid, ein kleines als Pupille. */
.rd-peek__mark {
  width: 20px;
  height: 13px;
  border: 0;
  border-radius: 0;
  background: var(--text-dim);
  clip-path: polygon(50% 0, 100% 40%, 100% 60%, 50% 100%, 0 60%, 0 40%);
}

.rd-peek__mark::after {
  content: "";
  position: absolute;
  inset-inline-start: 50%;
  top: 50%;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border: 0;
  border-radius: 0;
  background: var(--surface);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

[data-peek].is-on .rd-peek__mark { background: var(--accent-app); }


/* ---------- E-ink: jeder Sockel braucht eine Fassung auf Papier ----------- */

/* Auf Papier ist der Akzent ein Grauton und truege einen Sockel nicht
   mehr – dort zieht er Tinte. Schwarz, und die Kontur eines Feldes
   ebenso. */
html[data-eink] :is(.rd-btn, .rd-mini, .rd-iconbtn, .lib-round, .lib-shelf__more,
    .lib-next, .lib-tile__menu, .lib-sheet__cancel, .rd-join__btn, .rd-chip,
    .rd-tool, .rd-font, .rd-series__next, .rd-tile__menu, .ra-act, .ra-color,
    .rn-block__fold, .rn-block__act, .rn-jump, .rd-voice__btn, .rd-tts-add,
    .rd-voices-toggle, .rd-check__box) { --btn-lift: #000000; }

html[data-eink] .rd-btn {
  --btn-face: #1c1c1c;
  --btn-face-hover: #000000;
  color: #ffffff;
}

html[data-eink] .rd-btn--ghost {
  --btn-face: rgba(0, 0, 0, .10);
  --btn-face-hover: rgba(0, 0, 0, .18);
  color: #1c1c1c;
}

html[data-eink] .rd-btn--danger { --btn-face: rgba(0, 0, 0, .14); color: #1c1c1c; }

html[data-eink] .rd-chip.is-on,
html[data-eink] .rd-join__btn.is-on {
  --btn-face: #1c1c1c;
  color: #ffffff;
}

html[data-eink] .rd-seg__btn.is-on { background: #1c1c1c; color: #ffffff; }

html[data-eink] :is(.rd-input, .lib-search input) { box-shadow: inset 0 0 0 1.5px #1c1c1c; }
html[data-eink] :is(.rd-input, .lib-search input):focus { box-shadow: inset 0 0 0 2.5px #000000; }
html[data-eink] .rd-check__box { box-shadow: inset 0 0 0 2px #1c1c1c; }
html[data-eink] .rd-check input:checked + .rd-check__box { --btn-face: #1c1c1c; }
html[data-eink] :is(.rd-voice, .rd-voices-drawer, .rd-tts-voice) { box-shadow: inset 0 0 0 1px #1c1c1c; }
html[data-eink] .rn-passage { box-shadow: inset 3px 0 0 #1c1c1c; }
html[data-eink] .rd-goalring::before { background: #ffffff; }
html[data-eink] .ra-grip { background: #000000; }
html[data-eink] .rd-peek__mark::after { background: #ffffff; }

/* Die fuenf Farbfelder im Balken – hier steht !important, und zwar
   mit Grund. (In styles/eink.css steht es aus demselben Grund drei
   Dutzend Mal: auf Papier muss eine Farbe weichen, die woanders
   gesetzt wurde.)
   ------------------------------------------------------------------
   Die Farbe eines Feldes kommt aus dem Markup (colorRow() in
   app/reader/annotate.js schreibt sie als style="background:…"). Ein
   Attribut-Stil steht ueber jeder Regel eines Stilblatts; ohne
   !important laesst er sich von hier aus nicht erreichen.

   Auf Papier MUSS er erreicht werden. Die Markierungen im Text
   werden zu fuenf Graustufen (siehe styles/eink.css, .ra--*) – die
   Felder blieben bunt. Man waehlte dann Gelb und bekaeme Grau zu
   sehen, und zwei Felder, die auf dem Papier gleich aussehen, waeren
   im Balken nicht unterscheidbar. Dieselben fuenf Stufen, dieselbe
   Reihenfolge: was man drueckt, ist was man sieht.

   Der saubere Weg waere, die Farbe als --ra ans Element zu schreiben
   statt als background. Das gehoert in den Umbau des Balkens; bis
   dahin steht die Regel hier. */
html[data-eink] .ra-color[data-color="sun"] { --btn-face: #9a9a9a !important; --btn-face-hover: #9a9a9a !important; }
html[data-eink] .ra-color[data-color="moss"] { --btn-face: #8a8a8a !important; --btn-face-hover: #8a8a8a !important; }
html[data-eink] .ra-color[data-color="sky"] { --btn-face: #7a7a7a !important; --btn-face-hover: #7a7a7a !important; }
html[data-eink] .ra-color[data-color="rose"] { --btn-face: #6a6a6a !important; --btn-face-hover: #6a6a6a !important; }
html[data-eink] .ra-color[data-color="clay"] { --btn-face: #5a5a5a !important; --btn-face-hover: #5a5a5a !important; }

/* Ausgewaehlt heisst auf Papier: ein schwarzer Rahmen nach innen.
   Der graue Rahmen der Bildschirmfassung ginge zwischen fuenf
   Graustufen unter. */
html[data-eink] .ra-color.is-on { outline-color: #000000; }


/* =========================================================
   Touch type: das eigene Raster ("Custom")

   Die sechste Kachel und ihr Editor. Formensprache wie ueberall:
   die Seite ist eine FLAECHE (Eckschnitt), die Zellen darin sind
   Rasterfelder unter der 30px-Schwelle (rechteckig, kein Sockel –
   ein Sockel je Zelle machte aus 60 Zellen 60 Knoepfe, die alle
   gleich laut sind). Knoepfe sind nur −/+ und die zwei Handgriffe
   darunter: .rd-mini, rechter Winkel mit Sockel.
   ========================================================= */

/* Die aktive Kachel. Ihr Zustand lag auf border-color – und den
   Rand gibt es seit dem Eckschnitt nicht mehr. Er liegt jetzt in der
   inneren Kontur, die den Schnitt mitnimmt. */
.rd-zp.is-on .rd-zp__page { box-shadow: inset 0 0 0 2px var(--accent-app); }

.rd-zp__label small { font-size: max(var(--fs-floor), 10px); color: var(--text-faint); font-weight: 400; }

/* Die Vorschau der Kachel: dasselbe Raster in klein, Fugen statt Linien. */
.rd-zp__page--grid {
  display: grid;
  gap: 1px;
  padding: 3px;
}

.rd-zp__cell { min-width: 0; min-height: 0; }
.rd-zp__cell.is-turn { background: rgba(var(--t-reader), .42); }
.rd-zp__cell.is-menu { background: rgba(var(--o), .10); }
.rd-zp__cell.is-none { background: transparent; }

/* ---------- Der Editor ---------- */

.rd-gridedit {
  display: grid;
  gap: 14px;
  padding: 14px;
  --cut: 14px;
  clip-path: var(--cut-clip);
  background: rgba(var(--o), .03);
  box-shadow: inset 0 0 0 1.5px var(--line-strong);
  animation: rd-gridedit-in var(--dur) var(--ease-out);
}

.rd-gridedit[hidden] { display: none; }

@keyframes rd-gridedit-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

.rd-gridedit__dims {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.rd-step {
  display: grid;
  grid-template-columns: 32px 1fr 32px;
  grid-template-rows: auto 32px;
  column-gap: 6px;
  row-gap: 6px;
  align-items: center;
}

.rd-step__label {
  grid-column: 1 / -1;
  font-size: max(var(--fs-floor), 11px);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.rd-step__btn {
  width: 32px;
  height: 32px;
  padding: 0;
  font-size: 18px;
  line-height: 1;
  color: var(--text);
}

/* Unter der Schwelle: das Zahlfeld ist 32px hoch, ein Schnitt ginge
   durch die Ziffern. Rechteckig, aber nicht rund. */
.rd-step__num {
  height: 32px;
  padding: 0 4px;
  text-align: center;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  clip-path: none;
  border-radius: 0;
  -moz-appearance: textfield;
}

.rd-step__num::-webkit-inner-spin-button,
.rd-step__num::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

/* Die vier Pinsel. Das Zeichen vor dem Wort zeigt die Farbe, in der
   die Rolle auf der Seite erscheint. */
.rd-gridedit__brushes .rd-brush {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 7px 4px;
}

.rd-brush__mark {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 14px;
  font-size: max(var(--fs-floor), 10px);
  line-height: 1;
  letter-spacing: 0;
}

.rd-brush__mark.is-turn { background: rgba(var(--t-reader), .30); color: var(--accent-app); }
.rd-brush__mark.is-menu { background: rgba(var(--o), .10); color: var(--text-dim); font-size: max(var(--fs-floor), 7px); }
.rd-brush__mark.is-none { box-shadow: inset 0 0 0 1px rgba(var(--o), .22); }

.rd-brush.is-on .rd-brush__mark { background: rgba(0, 0, 0, .18); color: inherit; box-shadow: none; }

/* Die Seite zum Bemalen. Seitenverhaeltnis wie die Kacheln, damit das
   Raster hier so aussieht wie darueber. touch-action: none – sonst
   rollt das Fenster, statt dass der Finger malt. */
.rd-gridedit__page {
  display: grid;
  gap: 2px;
  width: min(100%, 230px);
  aspect-ratio: 3 / 4;
  margin: 0 auto;
  padding: 4px;
  --cut: 12px;
  clip-path: var(--cut-clip);
  background: var(--g-47);
  box-shadow: inset 0 0 0 1.5px var(--line-strong);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.rd-cell {
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  font-size: var(--cell-font, 12px);
  line-height: 1;
  cursor: crosshair;
  transition: background-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.rd-cell.is-turn { background: rgba(var(--t-reader), .30); color: var(--accent-app); }
.rd-cell.is-menu { background: rgba(var(--o), .08); color: var(--text-dim); letter-spacing: 1px; }
.rd-cell.is-none { background: transparent; box-shadow: inset 0 0 0 1px rgba(var(--o), .10); }

.rd-cell:hover { filter: brightness(1.25); }
.rd-cell:focus-visible { outline: 2px solid var(--accent-app); outline-offset: -2px; }

.rd-gridedit__acts { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.rd-gridedit__acts .rd-mini { padding: 7px 12px; }

.rd-gridedit__hint {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  text-align: center;
  color: var(--text-faint);
}

/* Auf der Seite: die Zellen des eigenen Rasters liegen buendig
   aneinander. Ein halber Pixel Abstand haelt zwei gleichfarbige
   Nachbarn auseinander, ohne dass Luecken zum Tippen entstehen. */
.rd-zone--cell { box-sizing: border-box; }
.rd-zone--turn.has-border { color: var(--accent-app); }

/* ---------- E-ink ---------- */

html[data-eink] .rd-zp.is-on .rd-zp__page { box-shadow: inset 0 0 0 2.5px #000000; }
html[data-eink] .rd-gridedit,
html[data-eink] .rd-gridedit__page { box-shadow: inset 0 0 0 1.5px #1c1c1c; background: #ffffff; }
html[data-eink] :is(.rd-cell, .rd-zp__cell, .rd-brush__mark).is-turn { background: #1c1c1c; color: #ffffff; }
html[data-eink] :is(.rd-cell, .rd-zp__cell, .rd-brush__mark).is-menu { background: #d0d0d0; color: #1c1c1c; }
html[data-eink] :is(.rd-cell, .rd-brush__mark).is-none { box-shadow: inset 0 0 0 1px #1c1c1c; }
html[data-eink] .rd-gridedit { animation: none; }
html[data-eink] .rd-cell:hover { filter: none; }

/* Night Pond (0.6.0 beta): die getönten Knöpfe dieses Bereichs tragen
   dieselbe Kante wie das „+" auf Home – 1,5 px im vollen Ton, auf der
   Fläche (::after) statt am Element, wo die deckende Fläche sie verdeckte.
   Fläche, Sockel und Schrift kommen aus --tint-* (styles/pond.css). */
.rd-btn--ghost::after,
.lib-next::after,
.rd-series__next::after,
.rn-jump::after,
.rd-tts-add::after { box-shadow: inset 0 0 0 1.5px var(--tint-edge); }
.rd-btn--ghost,
.lib-next,
.rd-series__next,
.rn-jump,
.rd-tts-add { color: var(--tint-ink); filter: var(--tint-glow); }

/* Buchdatei nicht auf diesem Gerät (app/reader/library.js, markAway): eine
   Marke oben am Cover – klein, also ohne Schnitt und ohne Rundung. */
.lib-tile__away {
  position: absolute;
  inset-inline: 6px;
  top: 6px;
  padding: 3px 6px;
  border-radius: 0;
  background: rgba(var(--o-deep), .72);
  backdrop-filter: blur(4px);
  font-size: max(var(--fs-floor), 10px);
  font-weight: 600;
  line-height: 1.3;
  color: var(--g-01);
  text-align: start;
  pointer-events: none;
}
.lib-tile:has(.lib-tile__away) .lib-tile__cover { opacity: .55; }
/* Der Menüknopf sitzt oben rechts – die Marke weicht ihm aus. */
.lib-tile__open .lib-tile__away { inset-inline-end: 36px; }

.rd-blank__vault { font-size: .82rem; color: var(--text-dim); }
.rd-blank__vault[hidden] { display: none; }

html[data-eink] .lib-tile__away { background: rgba(255, 255, 255, .92); color: #000000; outline: 1px solid #000000; }
html[data-eink] .lib-tile:has(.lib-tile__away) .lib-tile__cover { opacity: 1; }
