/* ═══════════════════════════════════════════════════════════════════
   Camera Obscura — das gesamte Design, eine Datei.

   Derselbe achtteilige Aufbau wie quiet.css, und die Reihenfolge ist
   funktional, nicht kosmetisch: die @font-face-Regeln zuerst, damit
   der Browser die Schriftanforderung schon kennt, bevor die erste
   Regel sie braucht; danach die Tokens, weil jede folgende Regel sie
   liest; die Umfrage nach den Komponenten, weil .uhr und .vorschau
   auf .knopf und .feld aufsetzen und nichts von dem umgekehrt; die
   Breakpoints am Ende, weil sie --rand-x ueberschreiben und dafuer
   spaeter in der Kaskade stehen muessen.

   (1) @font-face  (2) Tokens  (3) Grundlage  (4) Komponenten
   (5) Umfrage  (6) Breakpoints  (7) Bewegung  (8) Druck

   Keine Farbe ausserhalb des Token-Blocks. Zwei Gewichte, 400 und
   700: Plex Mono liegt nur fett vor, und weder Helvetica Neue noch
   Arial haben einen Schnitt zwischen 500 und 700. Ein 600 sucht der
   Browser zuerst aufwaerts (ueber 500 erst schwerere Schnitte): auf
   Apple-Geraeten und unter Windows wird es 700 und ist von fett nicht
   zu unterscheiden, auf Android ab 12 (Roboto variabel, mit eigenem
   600) ein echtes Halbfett. Dasselbe Gewicht saehe also je nach Geraet
   anders aus, und das Gewicht traegt hier Information, die die Farbe
   nicht allein tragen darf.

   Raster, Farben und Massstab stammen aus quiet.css, die Schrift aus
   dem Entwurf in Figma: die beiden Titelstufen in IBM Plex Mono
   (Seitentitel, Uhr, in uebersicht.css die Kennzahlen), alles andere
   in Helvetica Neue, in vier Stufen (Tokenblock) — bis auf die Pfeile,
   die in Plex stehen, weil Helvetica Neue keine hat. Dazu der rote
   Akzent aus demselben Entwurf und die Trefferflaechen. quiet-pages
   ist eine Leseseite am Schreibtisch, Camera Obscura ein Formular im
   Gehen, unter Zeitdruck, mit einer Hand. Die 27px hohen Zeilen aus
   schreibtisch.css sind deshalb NICHT uebernommen worden, obwohl
   schreibtisch.css die einzige Formularvorlage des Hausstils ist:
   Knoepfe, Felder und Antworten sind hier 56px hoch. Den Grad gibt
   dagegen der Entwurf vor, und der liegt mit 12px sogar unter den 13px
   von dort — kleiner wird die Schrift, nicht das Ziel.
   ═══════════════════════════════════════════════════════════════════ */

/* ------------------------------------------------------------------
   IBM Plex Mono — SIL OFL 1.1, © 2017 IBM Corp., Reserved Font Name
   „Plex". Lizenz: static/fonts/LICENSE-IBM-Plex.txt, neben den
   Dateien, wie es die OFL verlangt. Die Dateien sind UNVERAENDERT aus
   IBMs npm-Paket @ibm/plex-mono 2.5.0 (fonts/split/woff2): ein eigenes
   Subset waere nach der OFL eine veraenderte Fassung und duerfte nicht
   mehr „Plex" heissen.

   Nur der fette Schnitt, weil der Entwurf Plex Mono nur fett setzt —
   Titel, Uhr, Pfeile. Davon zwei Teile mit IBMs eigener unicode-range:
   Latin1 (18 KB) traegt jeden Titel, der Teil „Pi" (14 KB) die Pfeile
   und wird nur geladen, wenn auf der Seite einer steht. Der ganze
   Schnitt waere 50 KB fuer Zeichen, die hier nie vorkommen.

   Kein local() im src, anders als in IBMs eigener CSS: eine
   installierte, womoeglich aeltere Plex auf dem Rechner eines Besuchers
   gewaenne sonst gegen die Datei, die hier geprueft ist.
   ------------------------------------------------------------------ */
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-Bold-Latin1.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
  unicode-range: U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+02C6, U+02DA,
                 U+02DC, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022,
                 U+2026, U+2030, U+2039-203A, U+2044, U+20AC, U+2122, U+2212,
                 U+FB01-FB02;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-Bold-Pi.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
  unicode-range: U+03C0, U+0E3F, U+2000-200D, U+2010-2012, U+2015, U+2028-2029,
                 U+202F, U+2032-2033, U+203E, U+205F, U+2070, U+2074-2079,
                 U+2080-2089, U+2113, U+2116, U+2126, U+212E, U+2150-2151,
                 U+2153-215E, U+2190-2199, U+21A9-21AA, U+21B0-21B3, U+21B6-21B7,
                 U+21BA-21BB, U+21C4, U+21C6, U+2202, U+2206, U+220F, U+2211,
                 U+2215, U+2219-221A, U+221E, U+222B, U+2236, U+2248, U+2260,
                 U+2264-2265, U+2400-2421, U+2500-259F, U+25CA, U+2713, U+274C,
                 U+2B0E-2B11, U+3000, U+FEFF, U+FFFD;
}

/* Die Ersatzschnitte: was auf dem Bildschirm steht, bis Plex geladen
   ist. Auf einem Telefon im Mobilfunk ist das der erste Satz jeder
   Seite und nicht der Ausnahmefall, und ohne Angleichung sprangen die
   Titel beim Umschalten in Breite und Grundlinie.

   Monospace-Systemschriften, auf Plex gezogen: size-adjust macht jedes
   Zeichen genau 0,6 em breit wie in Plex (Vorschub der Ersatzschrift
   zu 600/1000), ascent- und descent-override setzen Plex' Hoehen (1025
   und 275 von 1000, kein Zeilenabstand) — geteilt durch size-adjust,
   weil der Browser die Overrides mit der angepassten Groesse
   multipliziert. Nachgemessen in Chromium: 24 Zeichen bei 64px sind in
   Plex 1121,28px breit, in Menlo mit diesen Werten 1121,27px.

   Drei Familien und nicht eine, weil die Werte an der Regel haengen und
   nicht an der Datei, die gewinnt: Consolas braucht 109 Prozent, die
   anderen knapp 100. Consolas steht vor der dritten Gruppe, sonst
   gewaenne auf Windows Courier New. Android hat nur Droid Sans Mono in
   400; fuer fett faellt es auf monospace und rechnet den Schnitt aus.
   Safari (auch auf iOS) kennt von den vier Descriptoren nur
   size-adjust: die Breite stimmt dort trotzdem, die Grundlinie liegt
   bis zum Umschalten rund 2px hoeher. */
@font-face {
  font-family: "IBM Plex Mono Ersatz";
  src: local("Menlo-Bold"), local("Menlo Bold"),
       local("DejaVuSansMono-Bold"), local("DejaVu Sans Mono Bold");
  font-weight: 700; font-style: normal;
  size-adjust: 99.66%;
  ascent-override: 102.85%;
  descent-override: 27.59%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "IBM Plex Mono Ersatz Consolas";
  src: local("Consolas Bold"), local("Consolas-Bold");
  font-weight: 700; font-style: normal;
  size-adjust: 109.13%;
  ascent-override: 93.92%;
  descent-override: 25.20%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "IBM Plex Mono Ersatz Liberation";
  src: local("LiberationMono-Bold"), local("Liberation Mono Bold"),
       local("RobotoMono-Bold"), local("Roboto Mono Bold"),
       local("CourierNewPS-BoldMT"), local("Courier New Bold");
  font-weight: 700; font-style: normal;
  size-adjust: 99.98%;
  ascent-override: 102.52%;
  descent-override: 27.50%;
  line-gap-override: 0%;
}

/* ═══════════════════════════════════════════════════════════════════
   (2) Tokens. Vier Einheitenregeln: Grade aus dem Entwurf, in vier
   Stufen und in px — jede Ausnahme begruendet an ihrer Zeile (die
   Eingabefelder, die Pfeile, der grosse Titel unter 390px); vertikale
   Abstaende immer calc(var(--rhythmus) * n); die Lesespalte in em, nie
   in ch; und keine Variable, die nicht benutzt wird.

   Raster und Farben sind aus quiet.css uebernommen, einschliesslich
   einiger Tokens, die Camera Obscura nicht anfasst (--spur,
   --sp-nummer): die beiden Dateien sollen dort nebeneinander diffbar
   bleiben, damit eine spaetere Korrektur an einem Kontrastwert in
   beiden Projekten dieselbe Zeile trifft. Die Schrift ist es nicht
   mehr — sie kommt aus dem Entwurf, mit eigenen Familien und eigenen
   Stufen —, und der Akzent ist rot statt bernsteinfarben. Beides steht
   an seiner Zeile begruendet.
   ═══════════════════════════════════════════════════════════════════ */

:root {
  /* ─── Schrift ─────────────────────────────────────────────────── */
  /* Zwei Familien aus dem Entwurf. Plex Mono fuer die Titel, die Uhr,
     die Kennzahlen der Uebersicht und die Pfeile (oben, mit
     Ersatzschnitten). Helvetica Neue fuer
     alles andere, und zwar als Systemschrift: Apple liefert sie auf
     jedem Mac und jedem iPhone mit, als Webfont mitliefern duerfte
     man sie nur mit einer gekauften Lizenz von Monotype — auch die
     Datei aus macOS nicht (Apples Lizenzvertrag, §2.E und §2.J). Wer
     kein Apple-Geraet hat, bekommt die naechste Verwandte: Arial unter
     Windows, Roboto unter Android, Liberation Sans oder Arimo unter
     Linux; auf deutschem Text weichen sie um weniger als zwei Prozent
     in der Breite ab. KEIN system-ui und kein -apple-system: auf Apple
     waere das San Francisco und eben nicht Helvetica Neue. */
  --schrift-titel: "IBM Plex Mono", "IBM Plex Mono Ersatz",
                   "IBM Plex Mono Ersatz Consolas",
                   "IBM Plex Mono Ersatz Liberation", monospace;
  --schrift-text: "Helvetica Neue", Helvetica, Arial, Roboto,
                  "Liberation Sans", Arimo, sans-serif;
  --gewicht-normal: 400;
  --gewicht-fett: 700;          /* Titel, „Teil 1.", Hervorhebungen */

  /* Die vier Stufen aus dem Entwurf (iPhone-Rahmen, 390px breit), je
     Grad, Zeilenabstand und Sperrung. Figmas Sperrung in Prozent ist
     em: 13 % sind .13em. Zeilenabstaende ohne Einheit, damit sie mit
     dem Grad gehen. */
  /* Titel gross: „Camera Obscura" auf dem ersten Bildschirm. 64px ab
     390px Breite, darunter mit der Breite kleiner: „Obscura" ist in
     Plex Mono mit dieser Sperrung 5,11 em breit, auf 320px stehen dafuer
     280px zur Verfuegung. 16,4vw haelt das Wort auf jeder Breite in einer
     Zeile; auf dem Schreibtisch deckelt rem es bei 64px. */
  --grad-titel-gross: clamp(2.5rem, 16.4vw, 4rem);
  --zeilen-titel-gross: 1.094;  /* 70/64 */
  --sperrung-titel-gross: .13em;
  /* Titel: jede Seitenueberschrift, die Abschnitte der Hinweise, die
     Uhr. */
  --grad-titel: 24px;
  --zeilen-titel: 1.25;         /* 30/24 */
  --sperrung-titel: .1em;
  /* Fliesstext. */
  --grad-text: 12px;
  --zeilen-text: 1.333;         /* 16/12 */
  --sperrung-text: .1em;
  /* Unterschrift und Kleingedrucktes: Fusszeile, Hinweise am Knopf,
     Beschriftungen. */
  --grad-klein: 10px;
  --zeilen-klein: 1.2;          /* 12/10 */
  --sperrung-klein: .19em;
  /* Beschriftung von Knoepfen, Antworten und Platzhaltern: im Entwurf
     im Grad des Fliesstexts, aber mit der Sperrung des Kleingedruckten
     — in allen Rahmen gleich, auch dort, wo der Fliesstext schon .1em
     hat. */
  --sperrung-bedienung: .19em;
  /* Die Ausnahme fuer Eingabefelder. NIE kleiner, auch wenn der
     Entwurf die Felder im Grad des Fliesstexts zeigt: unter 16px zoomt
     iOS Safari beim Fokus hinein und zoomt nicht zurueck. */
  --ui-eingabe: 16px;

  /* ─── Raster ──────────────────────────────────────────────────── */
  --rhythmus: 1.5rem;                            /* 24px, an rem gebunden */
  --satzmass: 40em;                              /* 72 Zeichen, 480px bei 12px */
  --satzmass-register: 69em;                     /* 828px bei 12px; quiet.css: 52em = 832px bei 16px */
  --spur: 10px;                                  /* Spalte des Jahrgangszeichens */
  --sp-nummer: 32px;                             /* 4 Ziffern à 0,6em @13px = 31,2px */
  --sp-luecke: 8px;
  --sp-etikett: 9em;                             /* Labelspalte im Essay-Kopf */
  --kopfhoehe: 40px;                             /* Obsidians --header-height */
  --rand-x: 20px;                                /* wird ab 40em/48em erhöht */
  --radius-s: 4px;
  --tempo: 140ms;                                /* nur für color/opacity */

  font-variant-numeric: lining-nums tabular-nums;
}

/* ─── Farbe: dunkel, und nur dunkel ───────────────────────────────
   Es gibt keine zweite Palette und keinen prefers-color-scheme-Zweig für
   den Bildschirm. Papier ist die Ausnahme: der Druckblock am Ende der
   Datei setzt alles auf Schwarz auf Weiß zurück.

   Alle Zahlen sind nachgerechnet (WCAG 2.x, sRGB), nicht geschätzt. Die
   Mischungen stehen bewusst in srgb und nicht in oklch: nur so ist die
   komponierte Fläche von Hand nachprüfbar.
   ─────────────────────────────────────────────────────────────────────── */
:root {
  color-scheme: dark;

  --grund:         #0e0e10;
  --flaeche-alt:   #16161a;   /* Eingabefelder — 1,1:1 zum Grund, nur eine Andeutung */
  --rahmen:        #2a2a30;   /* 1,35:1 — Dekor, trägt nie Information */
  --leitlinie:     color-mix(in srgb, #ffffff 9%, transparent);
  --flaeche-hover: color-mix(in srgb, #ffffff 6.5%, transparent);   /* = #1e1e20 */

  --text-normal: #e3e3e0;   /* 15,00:1 — Fließtext, Titel, Eingaben */
  --text-muted:  #adaeb3;   /*  8,71:1 — alles Chrome; Pflicht auf Hover-Flächen (dort 7,52:1) */
  --text-dim:    #8b8c93;   /*  5,76:1 — Weiterverweis, Fußnoten */
  --text-faint:  #5a5b62;   /*  2,85:1 — NUR Ornament, immer mit aria-hidden */
  --fokus:       #9a9ba2;   /*  6,96:1 zum Grund, 6,01:1 zur Hover-Fläche */

  /* Der Akzent ist ROT, das Rot aus dem Entwurf in Figma. Es kommt in
     zwei Stufen, weil ein einziges Rot hier nicht beides kann:

     --akzent-flaeche ist genau das Rot der Zeichnungen (#e30b17, alle
     Abbildungen unter static/abbildungen/ tragen es). Es ist Basis der
     drei Mischungen und die Kante der Knöpfe. Als SCHRIFT taugt es
     nicht: 3,97:1 zum Grund liegt unter den 4,5:1, die SC 1.4.3 für
     Text verlangt. Als Kante eines Bedienelements genügt es, SC 1.4.11
     verlangt dort 3:1 — und der Knopf trägt zusätzlich Fläche und
     Schrift.

     --akzent ist dasselbe Rot, aufgehellt, bis es als Schrift trägt:
     6,52:1 zum Grund, 6,11:1 auf der Pille, 5,61:1 auf der starken
     Pille. Die 7:1, die der Hausstil für Text anstrebt und die Bernstein
     mit 7,58:1 auf der Pille hatte, erreicht ein Rot dort erst als
     Lachston (#ff7a70, 7,12:1) — und der wäre nicht mehr das Rot des
     Entwurfs.
     Gewählt ist deshalb das hellste Rot, das noch nach Rot aussieht,
     und es hält AA an jeder Stelle, an der es steht. Nachgerechnet
     nach WCAG 2.x, die Mischungen über #0e0e10 komponiert.

     Hover hellt weiter auf, wie immer: #ffa89f, 10,43:1 zum Grund und
     8,98:1 auf der starken Pille. */
  --akzent:         #ff6157;   /*  6,52:1 zum Grund, 6,11:1 auf der Pille */
  --akzent-hover:   #ffa89f;   /* 10,43:1 — HELLT auf, senkt den Kontrast also nie */
  --akzent-flaeche: #e30b17;   /*  3,97:1 — das Rot der Zeichnungen; Mischungen, Knopfkante */
  --pille:       color-mix(in srgb, var(--akzent-flaeche) 12%, transparent);
  --pille-stark: color-mix(in srgb, var(--akzent-flaeche) 22%, transparent);
  --markierung:  color-mix(in srgb, var(--akzent-flaeche) 28%, transparent);   /* Text darauf 12,03:1 */

  /* Dringlichkeit — die zwei Töne der Uhr. Bis zum roten Akzent galt
     hier die Regel, Rot gehöre ausschliesslich der Uhr und Bernstein
     allem Bedienbaren: eine Farbe, die zugleich „hier tippen" und „die
     Zeit läuft" sagt, sagt keines von beidem mehr. Mit dem Entwurf ist
     der Akzent selbst rot geworden, und die Regel trägt nicht mehr.

     Was die Uhr seitdem vom Rest unterscheidet, ist nicht die Farbe,
     sondern Ort und Verhalten: sie steht als Einzige oben fest, ihr
     Balken ist das Einzige, was sich bewegt, und bei 0:30 kommen Puls
     und Formatwechsel der Zahl hinzu. Die beiden Töne bleiben eigene
     Token und an den Akzent nur angelehnt — der Balken ist ein wenig
     heller als die Knopfkante, damit er auf der dunklen Bahn als Fläche
     steht, und die Zahl in den letzten dreissig Sekunden heller als
     jede Schrift im Akzent, damit sie sich auch neben einem roten Knopf
     noch abhebt.

     Beides ist Rot von der ersten Sekunde an, nie Grün und nie Gelb.
     Eine Ampel über die Laufzeit wäre der naheliegende Entwurf und ist
     ausdrücklich nicht gewollt: Grün am Anfang hieße „noch viel Zeit",
     und die Umfrage hat zwei Minuten — es ist nie viel Zeit.

     Der helle Ton HELLT auf wie --akzent-hover, er dunkelt nicht nach:
     so kann der Kontrast bei der Betonung nie unter den Ausgangswert
     fallen, und das ist die Regel, die quiet.css für jede Hervorhebung
     anwendet. */
  --dringend:      #ef5350;   /*  5,53:1 — der Balken, ab der ersten Sekunde */
  --dringend-hell: #ff8f82;   /*  8,73:1 — die Zahl in den letzten 30 Sekunden */

  /* Alle Werte gegen --flaeche-alt gerechnet, alle über 7:1. */
  --syn-rot:     #e88b8b;   /* 7,30:1 */
  --syn-orange:  #dda05a;   /* 7,95:1 */
  --syn-gelb:    #cfc07a;   /* 9,86:1 */
  --syn-gruen:   #8cc79a;   /* 9,24:1 */
  --syn-cyan:    #7fc3c6;   /* 9,04:1 */
  --syn-blau:    #8fb4e0;   /* 8,40:1 */
  --syn-violett: #b3a2e0;   /* 7,87:1 */
  --syn-pink:    #d9a0bd;   /* 8,35:1 */
}

/* ═══ Grundlage ══════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }

html {
  scrollbar-gutter: stable;          /* kein Layoutsprung beim Scrollbalken */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  /* svh statt vh: auf Mobilgeraeten wuerde vh die Fusszeile unter die
     Browserleiste schieben. Der vh-Wert davor ist der Rueckfall. */
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background-color: var(--grund);
  color: var(--text-normal);
  font-family: var(--schrift-text);
  /* Der Fliesstext des Entwurfs als Grundgrad. Die Sperrung in em
     rechnet der Browser HIER in Pixel um und vererbt die Pixel — jede
     Regel mit eigenem Grad setzt deshalb auch ihre eigene Sperrung. */
  font-size: var(--grad-text);
  font-weight: var(--gewicht-normal);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
  overflow-wrap: break-word;
  hyphens: auto;                     /* braucht lang="de" am <html> */
  /* Der Trennstrich als U+002D. Ohne Vorgabe nimmt Chromium U+2010,
     und das liegt in Plex im Pi-Teil: jede Seite mit Uhr oder mit
     einem getrennten Titel holte sonst 14 KB fuer einen Strich. In
     Helvetica Neue und Arial sind beide Striche gleich breit. */
  -webkit-hyphenate-character: "-";
  hyphenate-character: "-";
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

::selection { background-color: var(--markierung); }   /* bewusst ohne color */

/* ═══ Komponenten ═══════════════════════════════════════════════════
   Alles, was auf mehr als einer Seite vorkommt. Die Umfragestuecke –
   Uhr, Vorschau, Fortschrittsknopf – stehen im Abschnitt darunter.
   ═══════════════════════════════════════════════════════════════════ */

/* ─── Sprungmarke ─────────────────────────────────────────────────
   Erster Tabstop jeder Seite. Auf den Schrittseiten steht die Uhr vor
   dem Inhalt, und die ist mit der Tastatur kein Ziel, aber sie steht
   im Lesefluss. Bewusst ohne Bedingung: ein konditionaler Skip-Link
   ist eine Fehlerquelle ohne Gegenwert.                             */
.sprung {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 20;                       /* ueber der Uhr, die auf 10 liegt */
  padding: var(--sp-luecke) var(--rand-x);
  background-color: var(--grund);
  color: var(--text-normal);
  font-size: var(--grad-text);
  letter-spacing: var(--sperrung-text);
  text-decoration: underline;
}
.sprung:focus-visible {
  left: 0;
  outline: 2px solid var(--fokus);
  outline-offset: -2px;
}

/* ─── Huelle: Polster am Blatt, Mass an der Spalte ────────────────
   .spalte aendert NIE ihren Schriftgrad – sonst laeuft ein Band mit
   eigener font-size aus der Achse (--satzmass ist in em).           */
.blatt {
  padding: calc(var(--rhythmus) * 1.5) var(--rand-x) 0;
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
.spalte {
  /* width: 100% ist Pflicht, weil .blatt eine Spalten-Flexbox ist: ein
     Flex-Element mit "margin-inline: auto" streckt sich in der
     Querachse NICHT, sondern schrumpft auf seinen Inhalt. */
  width: 100%;
  max-width: var(--satzmass);
  margin-inline: auto;
  padding-block-end: calc(var(--rhythmus) * 2);
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
.spalte > main { flex: 1 0 auto; }
.spalte > :first-child { margin-block-start: 0; }

/* ─── Titel und Mikrolabel ───────────────────────────────────── */
/* Jede Seitenueberschrift, im Titel des Entwurfs: Plex Mono fett,
   24/30, Sperrung .1em. OHNE Silbentrennung, wie im Entwurf: body
   trennt automatisch, und ein Titel wie „Wissen Sie, was Ihr zuletzt
   aufgenommenes Foto zeigt?" stand sonst mit „aufgenom-/menes" da,
   obwohl das Wort in die Zeile passt. Kein Wort in einem Seitentitel
   ist laenger als eine Zeile (gut 16 Zeichen auf 320px); faende sich
   doch eines, bricht overflow-wrap (body) es um. Die Abschnitte der
   Hinweise (.text h2) trennen dagegen weiter: „Anbieterkennzeichnung"
   ist in dieser Schrift breiter als die Spalte eines Telefons. */
.titel {
  margin: 0 0 .5em;
  hyphens: manual;
  font-family: var(--schrift-titel);
  font-size: var(--grad-titel);
  font-weight: var(--gewicht-fett);
  line-height: var(--zeilen-titel);
  letter-spacing: var(--sperrung-titel);
  color: var(--text-normal);
  text-wrap: balance;
}
/* Echte Versalien plus Sperrung, nie small-caps: wie im Entwurf
   („EINWILLIGUNG UND DATENSCHUTZ"), im Grad des Kleingedruckten und
   ohne Halbfett. 1.5x Rhythmus davor statt der 3x aus quiet.css: dort
   gliedert die Rubrik eine lange Registerseite, hier steht ueber jedem
   Schritt genau eine, und 72px Vorlauf haetten auf 375px die Frage unter
   die Faltung geschoben. */
.rubrik {
  margin: calc(var(--rhythmus) * 1.5) 0 calc(var(--rhythmus) * .5);
  font-size: var(--grad-klein);
  font-weight: var(--gewicht-normal);
  line-height: var(--zeilen-klein);
  letter-spacing: var(--sperrung-klein);
  text-transform: uppercase;
  color: var(--text-dim);
}
/* Beide Aufklappzeilen — das Rechtliche auf der Startseite, „Alle
   Angaben" in der Galerie — sind eine .rubrik und auf dem Telefon ein
   Ziel: 44px wie die Nebenlinks, 12px Zeile plus zweimal 16px Polster.
   Polster und nicht display: flex, denn ein summary mit anderem display
   als list-item verliert sein Dreieck. */
summary.rubrik {
  min-height: 44px;
  padding-block: 16px;
  cursor: pointer;
}

/* ─── Fliesstext ──────────────────────────────────────────────────
   Gebraucht auf der Startseite, /hinweise/, /danke/, /ende/,
   /widerruf/ und den Fehlerseiten. Reduziert auf das, was dort
   wirklich vorkommt: Absaetze, eine Ueberschriftenebene (h2), Listen,
   Links. Code, Tabellen, Fussnoten und
   Zitate aus quiet.css fehlen, weil diese Seiten sie nicht haben –
   und eine ungenutzte Regel ist eine Regel, die niemand nachprueft.
   Fliesstext des Entwurfs: 12/16, Sperrung .1em; die Abschnitte der
   Hinweise im Titel (h2). Eine weitere Ebene (h3) gibt es nicht. */
.text {
  margin-block-start: calc(var(--rhythmus) * 1.5);
  font-size: var(--grad-text);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
  color: var(--text-normal);
}
.text > :first-child { margin-block-start: 0; }
.text > :last-child  { margin-block-end: 0; }
.text :is(p, ul, ol, dl) { margin-block: .85rem; }
.text h2 { margin-block: .85rem; color: inherit; text-wrap: balance; }
.text :is(p, ul, ol, dl) + h2 { margin-block-start: 2rem; }
.text h2 {
  font-family: var(--schrift-titel);
  font-size: var(--grad-titel);
  font-weight: var(--gewicht-fett);
  line-height: var(--zeilen-titel);
  letter-spacing: var(--sperrung-titel);
}
.text :is(ul, ol) { padding-inline-start: 0; }
.text li { padding-block: .075em; margin-inline-start: 3ch; }
.text ul li::marker { color: var(--text-faint); }
.text ol li::marker { color: var(--text-muted); }
.text dt { color: var(--text-muted); }
.text dd { margin-inline-start: 3ch; }
/* Immer unterstrichen (nicht erst im Hover). Uebergang nur auf color,
   140ms – Flaechen werden nie animiert. */
.text a {
  color: var(--akzent);
  font-weight: var(--gewicht-normal);
  text-decoration-line: underline;
  text-decoration-thickness: auto;
  text-underline-offset: .15em;
  transition: color var(--tempo) ease-in-out;
}
@media (hover: hover) { .text a:hover { color: var(--akzent-hover); } }

/* ─── Knoepfe ─────────────────────────────────────────────────────
   56px und volle Spaltenbreite, nicht die 27px aus schreibtisch.css.
   SC 2.5.8 verlangt 24px, SC 2.5.5 verlangt 44px, Apple empfiehlt
   44pt – 56px, weil hier Zeitdruck, eine Hand in Bewegung und ein
   laufender Daumen zusammenkommen. Der Knopf ist ausserdem das
   einzige Ziel der Seite; Platz zu sparen hat hier keinen Gewinner.

   display: flex und nicht inline-block: nur damit zentriert der Text
   bei min-height zuverlaessig, ohne dass line-height die Hoehe
   mitbestimmt und bei zweizeiliger Beschriftung ueberlaeuft.        */
.knopf {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 56px;
  margin-block-start: calc(var(--rhythmus) * .5);   /* 12px zwischen gestapelten Knoepfen */
  padding: calc(var(--rhythmus) * .5) var(--rand-x);
  /* Die Kante im Rot der Zeichnungen, die Schrift im aufgehellten:
     siehe --akzent-flaeche im Tokenblock. */
  border: 1px solid var(--akzent-flaeche);
  border-radius: var(--radius-s);
  background-color: var(--pille);
  color: var(--akzent);
  /* Beschriftung wie im Entwurf: Grad des Fliesstexts, Sperrung des
     Kleingedruckten. Die 56px Hoehe bleiben — kleiner wird die
     Schrift, nicht das Ziel. */
  font-family: inherit;
  font-size: var(--grad-text);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-bedienung);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  /* Das graue Aufblitzen beim Tippen ist auf dieser Seite doppelt
     falsch: es ist Bewegung, und es kommt VOR der eigentlichen
     Reaktion, sieht also wie eine zweite Rueckmeldung aus. */
  -webkit-tap-highlight-color: transparent;
}
.knopf--still {
  background-color: transparent;
  color: var(--text-muted);
  border-color: var(--rahmen);
}
@media (hover: hover) {
  .knopf:hover { background-color: var(--pille-stark); }
  .knopf--still:hover { color: var(--text-normal); }
}
/* Der Fokusring muss am Label erscheinen, nicht am versteckten
   Datei-Input darin — :focus-within leistet das ohne :has(). */
.knopf:focus-within { outline: 2px solid var(--fokus); outline-offset: 2px; }
.knopf[disabled] { cursor: default; }

/* ─── Felder ──────────────────────────────────────────────────────
   font-size kommt aus --ui-eingabe und wird NIE mit einem kleineren
   Grad ueberschrieben — auch nicht mit dem Fliesstext des Entwurfs, der
   die Felder in 12px zeigt, und nicht fuer ein schmales Feld: unter 16px zoomt
   iOS Safari beim Fokus hinein und findet von allein nicht zurueck.
   Danach ist die sticky Uhr am oberen Rand ausserhalb des sichtbaren
   Ausschnitts, und der Zeitdruck ist unsichtbar geworden.           */
.feldgruppe {
  display: flex;
  flex-direction: column;
  gap: calc(var(--rhythmus) * .25);
  margin-block-start: calc(var(--rhythmus) * 1.5);
}
.feldgruppe > label {
  color: var(--text-muted);
  font-size: var(--grad-klein);
  line-height: var(--zeilen-klein);
  letter-spacing: var(--sperrung-klein);
}
.feld {
  width: 100%;
  min-height: 56px;
  padding: calc(var(--rhythmus) * .5) 12px;
  border: 1px solid var(--rahmen);
  border-radius: var(--radius-s);
  background-color: var(--flaeche-alt);
  color: var(--text-normal);
  font-family: inherit;
  font-size: var(--ui-eingabe);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
}
/* 7x Rhythmus = 168px, also etwa vier Zeilen plus Polster. Kein
   field-sizing: content – ein mitwachsendes Feld schoebe den Knopf
   beim Tippen nach unten, und der Daumen liegt schon dort.          */
.feld--mehrzeilig {
  min-height: calc(var(--rhythmus) * 7);
  resize: vertical;
}
.feld:focus-visible { outline: 2px solid var(--fokus); outline-offset: 2px; }
.feld::placeholder {
  color: var(--text-dim);
  /* Wie die Beschriftung der Knoepfe: Sperrung der Bedienung, hier am
     16px-Grad des Felds. Der getippte Text behaelt die des Fliesstexts. */
  letter-spacing: var(--sperrung-bedienung);
}

/* Ja/Nein als ganze Zeile. Der native Radioknopf ist auf dem Telefon
   etwa 13px gross und damit unter jeder Trefferflaechen-Vorgabe; das
   Kaestchen bleibt deshalb vorhanden und fokussierbar, aber die ZEILE
   ist das Ziel. NICHT display:none — dann faellt der Knopf aus der
   Tab-Reihenfolge und die Gruppe ist mit der Tastatur unerreichbar.  */
.wahl {
  position: relative;
  display: block;
  margin-block-start: calc(var(--rhythmus) * .5);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.wahl__eingabe {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
/* Die sichtbare Zeile ist das Geschwister des Kaestchens und nicht
   dessen Elternteil, obwohl .wahl:has(:checked) kuerzer waere: das
   Geschwisterpaar ist die Technik aus schreibtisch.css:80-86 und
   kommt ohne :has() aus. Faellt :has() auf einem aelteren Geraet aus,
   bliebe die Auswahl sonst voellig unsichtbar — das Kaestchen ist ja
   weggeclippt. Ein Ausfall, der das Formular unbedienbar macht, ist
   die paar Zeichen nicht wert. */
.wahl__text {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 56px;
  padding: calc(var(--rhythmus) * .5) var(--rand-x);
  border: 1px solid var(--rahmen);
  border-radius: var(--radius-s);
  background-color: var(--flaeche-alt);
  color: var(--text-normal);
  font-size: var(--ui-eingabe);
  line-height: var(--zeilen-text);
}
/* Die Flaeche traegt die Auswahl, der Rahmen verstaerkt sie: Farbe ist
   nie das einzige Merkmal (SC 1.4.1). */
.wahl__eingabe:checked + .wahl__text {
  border-color: var(--akzent);
  background-color: var(--pille);
  color: var(--akzent);
}
/* Der Fokusring muss an der Zeile erscheinen, nicht am weggeclippten
   Kaestchen — dort waere er zwei Pixel gross und unauffindbar. */
.wahl__eingabe:focus-visible + .wahl__text {
  outline: 2px solid var(--fokus);
  outline-offset: 2px;
}

/* ─── Vorspann ────────────────────────────────────────────────────
   Der Satz unter einem Seitentitel, der sagt, worum es auf der Seite
   geht. Im Entwurf Fliesstext und weiss, nicht Kleingedrucktes: er IST
   die Frage oder die Anleitung, und auf dem E-Mail-Schritt steht darin
   die Folge der Entscheidung (texte.SCHRITT_EMAIL) — beides soll man
   nicht als Fussnote lesen. */
.vorspann {
  margin: var(--rhythmus) 0 0;
  color: var(--text-normal);
  font-size: var(--grad-text);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
  text-wrap: pretty;
}

/* ─── Hinweiszeilen ───────────────────────────────────────────────
   Das Kleingedruckte des Entwurfs: 10/12, Sperrung .19em. In --text-muted
   und nicht im Grau des Entwurfs (--text-dim): bei 10px sind 8,71:1
   statt 5,76:1 die Reserve, die so kleine Schrift braucht. Der Wortlaut
   einer Einwilligung steht noch eine Stufe heller (.hinweis--wortlaut).

   Leer bleibt die Zeile unsichtbar UND ohne Phantomabstand. Das ist
   Pflicht und nicht Feinschliff: foto.js leert sie bei jedem neuen
   Versuch, und ein stehengebliebener Abstand saehe aus, als fehlte
   dort etwas. Ausgenommen ist eine Live-Region (unten).             */
.hinweis {
  margin: var(--rhythmus) 0 0;
  color: var(--text-muted);
  font-size: var(--grad-klein);
  line-height: var(--zeilen-klein);
  letter-spacing: var(--sperrung-klein);
  text-wrap: pretty;
}
.hinweis:empty { display: none; }
/* Die Meldezeile unter dem Upload ist eine Live-Region (role="status").
   Leer bleibt sie im Baum, nur ohne Hoehe und Abstand: eine Region, die
   erst mit ihrem Text erscheint, sagen VoiceOver und NVDA meist nicht
   an — derselbe Grund wie an .nur-vorlesen. */
.hinweis[aria-live]:empty { display: block; margin: 0; }
/* Die Akzentfarbe der Seite und kein eigener Fehlerton: ein
   auffaelliges Aufnahmedatum ist kein Fehler des Besuchers, und ein
   fehlgeschlagener Upload ist kein Fehler, den er begangen hat. Seit dem
   Entwurf ist der Akzent rot; ein zweites, „richtiges" Fehlerrot daneben
   waere ein zweites Rot ohne zweite Bedeutung. */
/* Warnungen und Fehler stehen im Grad des Fliesstexts und nicht im
   Kleingedruckten: wer sich vertippt hat oder dessen Upload
   gescheitert ist, soll das lesen, ohne es zu suchen. Ebenso die
   Meldezeile unter dem Upload (#foto-meldung), die Fehler und den
   Stand einer Live-Photo-Umwandlung traegt — dort aber ohne Rot,
   weil „wird vorbereitet" keine Warnung ist. */
.hinweis--warnung,
.hinweis--meldung {
  font-size: var(--grad-text);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
}
.hinweis--warnung { color: var(--akzent); }
/* Der Wortlaut einer Einwilligung, wo er am Knopf steht: die sichtbare
   Zeile ueber „Beginnen" und die beiden Saetze ueber den Knoepfen der
   Freigabe. Klein, wie es der Entwurf will, aber in --text-normal und
   nicht im leisen Ton der uebrigen Hinweise: klein und leise zugleich
   waere er Kleingedrucktes, und das soll er nicht sein (Art. 7 Abs. 2
   DSGVO: leicht zugaenglich). Der ausfuehrliche Wortlaut im <details>
   der Startseite steht ohnehin im Fliesstext. */
.hinweis--wortlaut { color: var(--text-normal); }

/* Die Dauer im Fliesstext der Startseite. Im Akzent wie im Entwurf, wo
   sie rot im Text steht — und --akzent und NICHT --dringend: auf der
   Startseite laeuft keine Uhr, und der Ton der Dringlichkeit bleibt
   dem Moment vorbehalten, in dem es wirklich eng wird (.uhr--knapp).

   Zusaetzlich fett und nicht nur farbig: Farbe allein darf keine
   Information tragen (WCAG 2.2, SC 1.4.1). Wer die Seite in Graustufen
   oder mit eigener Farbgebung sieht, erkennt die Hervorhebung am
   Gewicht. Das Element ist ohnehin ein <strong>, die Regel setzt nur
   den Grad dieses Projekts statt des Browservorgabewerts. */
.zeitangabe {
  color: var(--akzent);
  font-weight: var(--gewicht-fett);
}

/* ─── Meldungen ───────────────────────────────────────────────────
   Was nach einer Weiterleitung zu sagen ist: „Sitzung abgelaufen",
   „keine Teilnahme zu dieser Adresse". Ganz oben in <main>
   (basis.html). Eine Flaeche und keine Farbe: eine Meldung ist eine
   Auskunft und kein Alarm, und der Akzent steht schon auf jedem Knopf
   — ein roter Kasten ueber der Seite saehe aus wie ein Fehler des
   Besuchers. Die Flaeche hebt ihn ab, der Rahmen schliesst ihn. */
.meldungen { margin-block-end: calc(var(--rhythmus) * 1.5); }
.meldung {
  margin: 0;
  padding: calc(var(--rhythmus) * .5) 12px;
  border: 1px solid var(--rahmen);
  border-radius: var(--radius-s);
  background-color: var(--flaeche-alt);
  color: var(--text-normal);
  font-size: var(--grad-text);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
  text-wrap: pretty;
}
.meldung + .meldung { margin-block-start: calc(var(--rhythmus) * .5); }

/* ─── Leitfrage ───────────────────────────────────────────────────
   Die Fragen, mit denen die Startseite ihre Abschnitte ankuendigt:
   „Erinnern Sie sich?" und „Wie nehmen Sie teil?". Im Entwurf mittig,
   klein und hell, und genau so hier: keine Ueberschrift im Grad von
   .titel, sondern eine Zeile im Grad des Fliesstexts, die den Blick
   nach unten fuehrt. Als <h2> fuer die Gliederung der Seite, mit eigenem
   Grad und Gewicht, damit der Browserwert nicht durchschlaegt. */
.leitfrage {
  margin: calc(var(--rhythmus) * 1.5) 0 0;
  color: var(--text-normal);
  font-size: var(--grad-text);
  font-weight: var(--gewicht-normal);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
  text-align: center;
  text-wrap: balance;
}

/* ─── Titel mit Zeichnung ─────────────────────────────────────────
   Der E-Mail-Schritt traegt neben dem Titel den gezeichneten Umschlag
   aus dem Entwurf. Nebeneinander und oben ausgerichtet; bricht der
   Titel um, bleibt die Zeichnung bei der ersten Zeile. flex: none, damit
   ein langer Titel die Zeichnung nicht zusammendrueckt. */
.titelzeile {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--rhythmus);
}
.titelzeile__bild { flex: none; margin-block-start: .4em; }
/* Im Flex-Container faellt der Rand unter dem Titel nicht mit dem
   Abstand des folgenden Vorspanns zusammen, sondern addiert sich:
   36px statt der 24px jeder anderen Seite. Den Abstand traegt deshalb
   allein der Vorspann. */
.titelzeile > .titel { margin-block-end: 0; }

/* ─── Abbildungen ─────────────────────────────────────────────────
   Die roten Zeichnungen aus dem Entwurf: Kreis, Kamera, Auge. Zierde,
   immer mit leerem alt, immer mittig, und mit width/height im Markup,
   damit die Seite beim Laden nicht springt — height: auto haelt dabei
   das Seitenverhaeltnis, wenn max-width greift. Ihr Rot ist das von
   --akzent-flaeche und steht in den Dateien selbst. */
.abbildung {
  display: block;
  max-width: 100%;
  height: auto;
  margin: calc(var(--rhythmus) * 1.5) auto 0;
}
/* Der Kreis ueber „Wie nehmen Sie teil?" steht dicht an seiner Frage,
   die Kamera auf der Seite zwischen den Teilen weit unter den Knoepfen:
   sie schliesst die Seite und soll nicht wie ein dritter Knopf wirken. */
.abbildung--kreis  { margin-block-start: calc(var(--rhythmus) * 1.5); }
.abbildung--kamera { margin-block-start: calc(var(--rhythmus) * 3); }
/* Das Auge des Endes, kleiner als auf der Startseite — wie im Entwurf. */
.abbildung--auge   { width: 108px; margin-block: calc(var(--rhythmus) * 2); }

/* ─── Der Pfeil zurueck ───────────────────────────────────────────
   Die Zeichnung aus dem Entwurf, rechts unter dem Inhalt. 56px
   Trefferflaeche wie die Knoepfe, auch wenn der Pfeil selbst 47px
   breit ist: der Link ist das Ziel, nicht das Bild darin. Nur auf
   Seiten ohne Uhr (teile/zurueck.html sagt warum). */
.zurueck {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin: calc(var(--rhythmus) * 1.5) 0 0 auto;
  border-radius: var(--radius-s);
  -webkit-tap-highlight-color: transparent;
}
.zurueck img { display: block; width: 47px; height: auto; }

/* ─── Trenner und Fusszeile ──────────────────────────────────── */
.trenner {
  border: 0;
  border-block-start: 1px solid var(--rahmen);
  margin: calc(var(--rhythmus) * 2) 0 0;
}
.leiste {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-luecke);
  margin-block-start: var(--rhythmus);
  /* Kleingedrucktes, im Grau des Entwurfs. */
  font-size: var(--grad-klein);
  line-height: var(--zeilen-klein);
  letter-spacing: var(--sperrung-klein);
  color: var(--text-dim);
}
/* 24px Trefferflaeche nach SC 2.5.8, erzeugt ueber die eigene Hoehe und
   NICHT ueber Polster plus negativen Rand wie quiet.css:950: die
   Fusszeile richtet ihre Kinder an der Grundlinie aus, und der
   Grundlinienabstand eines Flex-Elements wird ab seiner Rand-Kante
   gemessen. Ein negativer Rand verschoebe den Link also gegen die
   Zeile, in der er steht. Die paar Pixel, die die Zeile dadurch hoeher
   wird, kosten nichts — sie ist das letzte Element der Seite.

   Die Flaeche ist hier noetiger als frueher: bis zum Umbau stand ein
   einziger Link in der Zeile, jetzt stehen dort zwei — der Name fuehrt
   zur Startseite — und fuer Personal drei nebeneinander, und bei 10px
   Schrift sind zwei 12px hohe Ziele auf einem Telefon nicht sicher zu
   treffen. */
.leiste a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  color: inherit;
  text-decoration: none;
}
@media (hover: hover) { .leiste a:hover { color: var(--text-normal); } }
/* Die Quellenangabe links, die Fassung rechts — space-between an
   .leiste trennt genau ZWEI Kinder, und ohne diese Klammer waere die
   Fusszeile je nach is_staff zwei-, drei- oder vierteilig und die
   Fassung mal rechts, mal in der Mitte.

   Innen zentriert und nicht an der Grundlinie: die 24px hohen Links
   stehen neben 12px hohen Textstuecken, und zentriert ist das eine
   Zeile statt dreier Hoehen uebereinander. */
.leiste__quelle {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-luecke);
}
/* --text-faint ist die Stufe fuer Ornament und traegt hier nichts:
   der Punkt ist aria-hidden, der Abstand steht schon im gap. */
.leiste__punkt { color: var(--text-faint); }
/* Die Fassung ist kein Weiterverweis und kein Ziel, sondern eine
   Auskunft fuer den einen Fall, in dem jemand fragt "welcher Stand
   laeuft da?" — der vollstaendige Git-Stand haengt als title daran und
   nicht als Text, denn zwoelf Hex-Zeichen neben dem Hinweislink waeren
   Rauschen. Sie stand einmal eine Stufe leiser als der Rest der Zeile;
   seit dem Entwurf steht die ganze Zeile in --text-dim, und leiser geht
   es mit Information nicht. tabular-nums, damit die Zahl bei einem
   Deployment nicht die Breite der Zeile aendert. */
.leiste__fassung {
  font-variant-numeric: lining-nums tabular-nums;
}

/* ─── Unsichtbar, aber vorlesbar ──────────────────────────────────
   Traegt die aria-live-Region der Uhr. clip-path statt display:none,
   weil ein display:none-Knoten von Screenreadern nicht beobachtet
   wird und die vier Ansagen dann nie ankaemen.                      */
.nur-vorlesen {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ─── Fokusring: neutral grau, nie Akzent ─────────────────────────
   Das Rot traegt hier schon die Knoepfe, die Verweise und die Uhr; ein
   roter Fokusring waere das vierte Signal in derselben Farbe und auf
   einem roten Knopf schlicht unsichtbar. base-60 liefert 6,96:1 und
   bleibt unbunt.                                                     */
:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--fokus);
  outline-offset: 2px;
  border-radius: 2px;
}
:focus:not(:focus-visible) { outline: none; }

/* ═══ Umfrage ═══════════════════════════════════════════════════════
   Die drei Stuecke, die es nur hier gibt: die Uhr, die sprungfreie
   Vorschau und der Knopf, der sein eigener Fortschrittsbalken ist.
   ═══════════════════════════════════════════════════════════════════ */

/* ─── Die Uhr ─────────────────────────────────────────────────────
   Sie steht als direktes Kind von <body> VOR .blatt und klebt am
   oberen Rand. Der Widerspruch "minimalistisch aber praesent" ist
   ueber Position und Konstanz geloest, nicht ueber Groesse oder
   Farbe: die Uhr ist das einzige Element der Seite, das sich
   ueberhaupt bewegt.

   env(safe-area-inset-top) als Polster und nicht als Rand: auf einem
   iPhone im Querformat liegt der Balken sonst unter der Notch, und
   der Balken ist genau das Stueck, das immer sichtbar sein muss.    */
.uhr {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rhythmus);
  min-height: 44px;
  padding-inline: var(--rand-x);
  padding-block-start: env(safe-area-inset-top, 0px);
  background-color: var(--grund);
  border-block-end: 1px solid var(--rahmen);
}
/* ─── Bahn und Balken ─────────────────────────────────────────────
   Zwei Flaechen und nicht eine: die Bahn in --rahmen zeigt, wie viel
   FEHLT, der Balken darin, wie viel bleibt. Vorher lief der Balken
   randlos ueber die volle Breite und las sich als Kante des Fensters
   statt als Anzeige — der abgelaufene Teil war schlicht unsichtbar, und
   eine Leiste ohne sichtbares Ende hat keine Skala.

   Der Einzug ist --rand-x und keine eigene Zahl: es ist dieselbe
   Spalte, in der Titel, Felder und Knopf stehen, und erst dadurch steht
   die Leiste AUF der Seite statt an ihrem Rand.

   Geklemmt wird in der Bahn (overflow: hidden) und nicht am Balken: ein
   border-radius am Balken wuerde von scaleX mitgestaucht, und bei
   scaleX(.1) waere aus der Rundung ein 0,3px breiter Sporn geworden.
   Die Bahn wird nie skaliert, ihre Rundung bleibt deshalb ueber die
   ganze Laufzeit dieselbe.

   6px und nicht mehr die 4px von vorher: vier Pixel waren die Hoehe
   einer Kante, und eine Kante braucht weder Rundung noch Einzug. Als
   Element aus zwei Flaechen muss die Leiste als Leiste lesbar sein, und
   unter 6px ist von --radius-s (4px, vom Browser auf die halbe Hoehe
   geklemmt) nichts mehr zu erkennen. Acht waeren ein Band und zoegen
   den Blick dauerhaft von der Frage weg; sechs bleiben unter einem
   Siebtel der 44px hohen Kopfzeile.

   Die Hoehe ist KONSTANT: der urspruengliche Sprung von 2px auf 4px bei
   0:30 entfaellt. Den Zustandswechsel tragen die Farbe der Zahl und der
   Puls, und zwei gleichzeitige Signale an derselben Leiste — groesser
   UND pulsierend — ueberlagern einander nur.

   An der ABSOLUTEN Oberkante, nicht unter dem Polster: der Restanteil
   soll auch dann ablesbar sein, wenn vom Kopf nur noch ein Streifen aus
   dem Scroll herausschaut.

   inset-inline-start plus width statt inset-inline: mit left UND right
   UND einer Breite ist der Kasten ueberbestimmt, und welcher der drei
   Werte dann faellt, haengt an der Schreibrichtung. Eine Angabe weniger
   macht die Regel eindeutig. */
.uhr__bahn {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: var(--rand-x);
  width: calc(100% - var(--rand-x) * 2);
  height: 6px;
  border-radius: var(--radius-s);
  background-color: var(--rahmen);
  overflow: hidden;
}
/* width und scaleX teilen sich die Arbeit, und zwar nacheinander: ohne
   JavaScript steht am Balken die serverseitig gesetzte Breite aus
   teile/kopf.html. Sie rechnet seit dem Einzug gegen die BAHN und nicht
   mehr gegen die Kopfzeile — nur deshalb stimmt sie auch mit Einzug.
   Danach nimmt timer.js sie auf 100% zurueck und fuehrt den Anteil
   allein in scaleX (static/js/timer.js). Beides gleichzeitig waere ein
   Produkt und kein Wert.

   260ms und nicht 250: timer.js setzt scaleX viermal je Sekunde, der
   Uebergang zeichnet die Zwischenschritte, und die Ueberlappung von
   zehn Millisekunden verhindert, dass zwischen zwei Takten fuer einen
   Lidschlag Stillstand steht. Vorher sprang die Leiste viermal je
   Sekunde um je ein Viertelprozent und sah dadurch ruckweise aus.

   Ein Uebergang und NICHT eine CSS-Animation ueber die Restzeit: die
   waere der kuerzere Weg und waere falsch. Sie muesste bei jedem
   visibilitychange und jedem pageshow neu berechnet und neu gestartet
   werden, und genau dort entstuende die Abweichung zwischen Anzeige und
   Serveruhr, die das Messen-statt-Zaehlen ueberhaupt vermeiden soll.

   linear und nicht ease: eine Uhr laeuft gleichmaessig, und jede
   Beschleunigungskurve waere eine Aussage ueber die Zeit, die nicht
   stimmt. */
.uhr__balken {
  height: 100%;
  background-color: var(--dringend);
  transform-origin: left;
  transform: scaleX(1);
  transition: transform 260ms linear;
}
/* Kein Uebergang dort, wo zwischen altem und neuem Wert eine ganze
   Minute liegen kann: beim ersten Strich, bei der Rueckkehr aus dem
   Hintergrund und bei einer Seite aus dem bfcache. timer.js setzt die
   Klasse fuer genau einen Stilumbruch und nimmt sie sofort wieder. 260ms
   Fliessen ueber die halbe Leiste waeren eine Bewegung, die es in dieser
   Uhr sonst nirgends gibt — und sie liefe ausgerechnet in dem Moment,
   in dem jemand aus der Fotomediathek zurueckkommt. */
.uhr--sofort .uhr__balken { transition: none; }
/* Die Zahl im Titel des Entwurfs: Plex Mono fett, 24/30, wie dort
   oben rechts. Die Farbe folgt NICHT dem Entwurf, der sie von Anfang an
   rot zeigt: sie bleibt ruhig bis 0:30 und wechselt dann einmal
   (.uhr--knapp) — rot ab der ersten Sekunde ist der Balken.

   Gleichbleibende Breite ist Pflicht, nicht Geschmack: wechselt die
   Breite der Zahl jede Sekunde, schubst sie die Punkte, und DAS nimmt
   man als Flackern wahr, nicht die Farbe. Plex Mono ist monospaced,
   jedes Zeichen 0,6 em = 1ch breit; min-width haelt die Breite auch
   nach dem Formatwechsel auf zwei Ziffern: vier Zeichen samt ihrer
   Sperrung. tabular-nums aendert hier nichts, auch jede Ersatzschrift
   ist monospaced; es bleibt fuer den Fall, dass die Familie wechselt. */
.uhr__zahl {
  min-width: calc(4ch + 4 * var(--sperrung-titel));
  text-align: end;
  color: var(--text-muted);
  font-family: var(--schrift-titel);
  font-size: var(--grad-titel);
  font-weight: var(--gewicht-fett);
  line-height: var(--zeilen-titel);
  letter-spacing: var(--sperrung-titel);
  font-variant-numeric: lining-nums tabular-nums;
}
.uhr__punkte {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.uhr__punkt {
  width: 7px;
  height: 7px;
  border: 1px solid var(--text-muted);
  border-radius: 50%;
}
.uhr__punkt--erledigt { background-color: var(--text-muted); }

/* Genau EIN Zustandswechsel bei 0:30: timer.js setzt diese Klasse ein
   einziges Mal und nimmt sie nie zurueck (static/js/timer.js:205). Was
   danach laeuft, ist eine Bewegung und kein zweiter Wechsel.

   Der Puls ist langsam gewaehlt und nicht schnell: 1,2s je Durchlauf
   sind 0,83 Hz und damit weit unter den 3 Hz, ab denen SC 2.3.1 von
   Flackern spricht. Er ruehrt ausserdem nur die Deckkraft an und keine
   Groesse — eine wachsende und schrumpfende Flaeche an der Oberkante
   schoebe den Blick bei jedem Durchlauf neu an und waere unter
   Zeitdruck das Gegenteil von hilfreich.

   Dass die Leiste im dunkelsten Moment unter 3:1 faellt, ist hingenommen
   und kein Versehen: sie traegt aria-hidden, die Information steht in
   der Zahl daneben, und SC 1.4.11 nimmt rein dekorative Flaechen
   ausdruecklich aus. Die Zahl selbst bleibt bei 8,73:1. */
.uhr--knapp .uhr__zahl   { color: var(--dringend-hell); }
.uhr--knapp .uhr__balken { animation: uhr-puls 1.2s ease-in-out infinite; }

@keyframes uhr-puls {
  from, to { opacity: 1; }
  50%      { opacity: .55; }
}

/* Bei Ablauf weicht die Zahl einem Satz. Kein Modal, keine Umleitung,
   nichts gesperrt — der Ablauf hat null Konsequenz, und das ist die
   dritte der drei Kompensationen, mit denen die Essential Exception
   zu SC 2.2.1 ueberhaupt erst tragfaehig ist.
   font-size: 0 statt eines zweiten Elements: die Zahl behaelt ihr
   role="timer", und der Satz erscheint an genau derselben Stelle.
   min-width faellt dabei weg, sonst stuenden 4ch von 0px daneben.
   Der Satz steht im Fliesstext und nicht in der Schrift der Zahl. */
.uhr--aus .uhr__zahl { font-size: 0; min-width: 0; }
.uhr--aus .uhr__zahl::after {
  content: "Zeit abgelaufen — weiter geht's";
  font-family: var(--schrift-text);
  font-size: var(--grad-text);
  font-weight: var(--gewicht-normal);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
  color: var(--text-muted);
}
/* Mit dem Ablauf endet auch der Puls. Der Balken steht dann ohnehin auf
   scaleX(0) und ist unsichtbar — aber eine Animation, die niemand mehr
   sieht, laeuft im Compositor weiter, und sie wuerde einen Zustand
   betonen, der gerade aufgehoert hat zu draengen. Die Regel steht NACH
   .uhr--knapp und hat dieselbe Spezifitaet; nur deshalb gewinnt sie. */
.uhr--aus .uhr__balken { animation: none; }

/* ─── Vorschau ohne Sprung ────────────────────────────────────────
   Der Rahmen steht SCHON vor der Auswahl da. aspect-ratio geht nicht:
   das Seitenverhaeltnis des Fotos ist unbekannt (hoch, quer,
   Panorama). Eine feste Hoehe ist die einzige Loesung, die die
   Seitenhoehe beim Fuellen um exakt 0px aendert — und ein Sprung
   genau in dem Moment, in dem der Daumen zum Knopf wandert, kostet
   einen Fehlgriff.

   min(52vh, 420px): mehr als die halbe Fensterhoehe nimmt dem Knopf
   den Platz, mehr als 420px braucht eine Kontrollvorschau nicht.

   Seit dem Entwurf ist der Rahmen selbst ein Label des Datei-Inputs
   und oeffnet die Auswahl wie der Knopf darunter; daher der Zeiger. */
.vorschau {
  height: min(52vh, 420px);
  margin-block-start: var(--rhythmus);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  display: grid;
  place-items: center;
  border: 1px solid var(--rahmen);
  border-radius: var(--radius-s);
  overflow: hidden;
}
/* Gestrichelt heisst "hier kommt noch etwas hin", durchgezogen heisst
   "hier steht etwas". Der Rahmen traegt den Zustand, nicht die Farbe. */
.vorschau--leer { border-style: dashed; }
.vorschau__bild {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
}
/* Die Aufforderung im leeren Rahmen: im Entwurf wie ein Platzhalter,
   im Grad des Fliesstexts mit der Sperrung der Bedienung. Mit dieser
   Sperrung ist der Satz so breit wie der Rahmen eines Telefons; das
   Polster der Felder (12px) haelt ihn von der gestrichelten Kante weg,
   und bricht er um, steht er mittig wie im Entwurf. */
.vorschau__text {
  padding-inline: 12px;
  color: var(--text-dim);
  font-size: var(--grad-text);
  letter-spacing: var(--sperrung-bedienung);
  text-align: center;
}
/* Was gerade nicht gilt, wird ausgeblendet und nicht geleert: so
   bleibt das <img> im DOM und behaelt seinen alt-Text, und foto.js
   muss keine Knoten erzeugen. */
.vorschau--leer .vorschau__bild { display: none; }
.vorschau:not(.vorschau--leer) .vorschau__text { display: none; }
/* Manche HEIC-Dateien kann der Browser hochladen, aber nicht
   darstellen. Dann bleibt der Rahmen durchgezogen stehen und zeigt
   den Dateinamen — die Seite springt auch in diesem Fall nicht. */
.vorschau--ohne-bild .vorschau__bild { display: none; }
.vorschau--ohne-bild .vorschau__text { display: block; }

/* ─── Der Knopf IST der Fortschrittsbalken ────────────────────────
   Kein zusaetzliches Element, keine Layoutverschiebung, und der
   Fortschritt steht genau dort, wo der Blick nach dem Tippen ohnehin
   liegt. --fortschritt setzt foto.js als Inline-Eigenschaft; der
   Rueckfall 0% haelt den Knopf auch dann richtig, wenn das Skript
   zwischen classList.add und dem ersten progress-Ereignis abbricht.

   background-image und nicht background: die background-color aus
   .knopf bleibt darunter liegen und traegt den ungefuellten Teil.   */
.knopf--sendet {
  background-image: linear-gradient(to right,
      var(--pille-stark) 0 var(--fortschritt, 0%),
      transparent var(--fortschritt, 0%) 100%);
}
/* Waehrend des Uploads werden die leisen Knoepfe stillgelegt, nicht
   entfernt: entfernt saesse der Hauptknopf ploetzlich 68px weiter
   oben, unter einem Daumen, der schon dort liegt.

   Ausgenommen der leise Knopf, der GERADE sendet: seit der Freigabe
   kann „Abschicken ohne Zustimmung" selbst der gedrueckte sein, und
   ein Fortschritt auf einem halb durchsichtigen Knopf saehe aus wie
   einer, der nicht vorankommt. */
.formular--sendet .knopf--still:not(.knopf--sendet) {
  pointer-events: none;
  opacity: .4;
}

/* ─── Der Datei-Input ─────────────────────────────────────────────
   Er liegt IM Label des Knopfs: :focus-within greift dort ohne :has().
   Der Vorschaurahmen darueber ist ein zweites Label, ueber for/id —
   er oeffnet die Auswahl, ist aber kein Tabstop, und den Fokusring
   traegt allein der Knopf. Versteckt per clip-path und NIEMALS per
   display:none oder visibility:hidden — ein display:none-Input mit
   required laesst Chrome den Submit still abbrechen ("An invalid
   form control is not focusable") und faellt aus der Tab-Reihenfolge.
   Das Formular saehe dann aus, als reagierte der Knopf nicht.       */
.dateiwahl {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ─── Die Kopfzeile ohne Uhr ──────────────────────────────────────
   Auf dem E-Mail-Schritt und im zweiten Teil steht nur die Punktreihe
   (teile/kopf.html). Dieselbe Zeile, dieselbe Hoehe, dieselbe Kante —
   wer vom ersten in den zweiten Teil wechselt, soll an der Kopfzeile
   sehen, dass die Uhr fehlt, und nicht, dass sich die Seite geaendert
   hat. Sie klebt aber nicht: was sie zeigt, muss nicht ueber jedem
   Scrollen stehen, und eine klebende Leiste ohne Uhr naehme Platz,
   ohne etwas zu sagen. */
.uhr--ohne-zeit { position: static; }

/* ─── Antworten als Knoepfe ───────────────────────────────────────
   Die Auswahlfragen des zweiten Teils, eine Antwort je Knopf, wie die
   Ahnung im ersten. Abstand nach oben wie eine .feldgruppe, damit Frage
   und Antworten so weit auseinanderstehen wie Frage und Feld. */
.antworten { margin-block-start: calc(var(--rhythmus) * 1.5); }

/* ─── Zustimmung auf der Upload-Seite ─────────────────────────────
   Die Freigabe fuer Galerie und Ausstellung (schritt_foto.html). Die
   Zeile „Zustimmung" darueber steht wie im Entwurf im Fliesstext, nicht
   als Rubrik in Versalien. Der Text ueber jedem Knopf ist das, wozu er
   Ja sagt — und der obere ist die Einwilligung selbst; beide tragen
   deshalb .hinweis--wortlaut (oben bei den Hinweiszeilen). */
.freigabe { margin-block-start: calc(var(--rhythmus) * 1.5); }
.freigabe__titel {
  margin: 0;
  color: var(--text-normal);
  font-size: var(--grad-text);
  font-weight: var(--gewicht-normal);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
}

/* ─── Der Schieberegler ───────────────────────────────────────────
   Ein natives <input type="range"> mit der Spur und dem Knopf aus dem
   Entwurf. Nativ, weil es ohne Skript bedienbar ist, mit Pfeiltasten
   auch, und der Browser seinen Wert ansagt; ein nachgebauter Regler
   muesste all das selbst leisten. Gezeichnet sind nur Spur und Knopf.

   44px Hoehe fuer das ganze Feld und nicht die 6px der Spur: getroffen
   wird das Feld, nicht die Linie. Die Pseudoelemente stehen je zweimal,
   fuer WebKit und fuer Firefox, weil ein Selektor mit einem
   unbekannten Pseudoelement die ganze Regel ungueltig macht — beide in
   einer Regel waeren in jedem Browser keine.

   margin-top am WebKit-Knopf: dort sitzt er an der OBERKANTE der Spur
   und nicht mittig; (6 - 25) / 2 = -9,5px holt ihn auf die Linie.
   Firefox zentriert von selbst. */
.regler { margin-block-start: calc(var(--rhythmus) * 2); }
.regler__eingabe {
  display: block;
  width: 100%;
  height: 44px;
  margin: 0;
  background: transparent;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
}
.regler__eingabe::-webkit-slider-runnable-track {
  height: 6px;
  background: url("../abbildungen/regler-bahn.svg") center / 100% 6px no-repeat;
}
.regler__eingabe::-moz-range-track {
  height: 6px;
  background: url("../abbildungen/regler-bahn.svg") center / 100% 6px no-repeat;
}
.regler__eingabe::-webkit-slider-thumb {
  width: 15px;
  height: 25px;
  margin-top: -9.5px;
  border: 0;
  background: url("../abbildungen/regler-knopf.svg") center / contain no-repeat;
  -webkit-appearance: none;
  appearance: none;
}
.regler__eingabe::-moz-range-thumb {
  width: 15px;
  height: 25px;
  border: 0;
  border-radius: 0;
  background: url("../abbildungen/regler-knopf.svg") center / contain no-repeat;
}
.regler__eingabe:focus-visible { outline: 2px solid var(--fokus); outline-offset: 2px; }
.regler__enden {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-luecke);
  color: var(--text-dim);
  font-size: var(--grad-klein);
  line-height: var(--zeilen-klein);
  letter-spacing: var(--sperrung-klein);
}
/* Die gelesene Zahl, von regler.js gesetzt. Die Hoehe steht schon vor
   dem ersten Wert, damit die Seite nicht springt, wenn er erscheint. */
.regler__wert {
  display: block;
  min-height: 1.4em;
  margin-block-start: calc(var(--rhythmus) * .5);
  color: var(--text-normal);
  font-size: var(--grad-text);
  letter-spacing: var(--sperrung-text);
  text-align: center;
  font-variant-numeric: lining-nums tabular-nums;
}

/* ─── Der Auftakt der Startseite ──────────────────────────────────
   Der erste Bildschirm aus dem Entwurf: Titel, Projektzeile und Auge in
   der Mitte, unten die Frage und darunter der Pfeil. Er fuellt die
   Hoehe des Fensters abzueglich des Polsters von .blatt, damit Frage
   und Pfeil genau auf der Unterkante des ersten Bildschirms stehen —
   dort, wo ein Hinweis „weiter unten geht es weiter" hingehoert.
   svh und nicht vh, aus dem Grund, der an body steht; der vh-Wert davor
   ist der Rueckfall.

   Die Mitte schiebt sich mit margin-block: auto zwischen Oberkante und
   Frage und nicht mit justify-content: eine Seite, die niedriger ist als
   ihr Inhalt, soll scrollen und nicht ueberlappen. */
.auftakt {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: calc(100vh - var(--rhythmus) * 1.5);
  min-height: calc(100svh - var(--rhythmus) * 1.5);
  text-align: center;
}
.auftakt__mitte {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-block: auto;
  padding-block: calc(var(--rhythmus) * 2);
}
/* inline-size: min-content legt jedes Wort auf eine eigene Zeile, wie im
   Entwurf, ohne dass ein Umbruch im Markup stuende — der Titel ist
   kontext.SEITENTITEL und steht so auch im <title>.

   hyphens: manual ist dabei Pflicht und keine Feinheit: body trennt
   automatisch, und mit Silbentrennung ist min-content die breiteste
   SILBE und nicht das breiteste Wort. Der Titel stand so als „Ca-/mer/
   a/Ob-/scu-/ra" auf der Seite, sechs Zeilen statt zwei.

   Das Polster links ist so breit wie die Sperrung: der Browser setzt
   die Sperrung auch HINTER den letzten Buchstaben jeder Zeile, und ohne
   Gegengewicht stuende der mittig gesetzte Titel um eine halbe Sperrung
   (bei 64px gut 4px) nach links verschoben. */
.auftakt__titel {
  inline-size: min-content;
  hyphens: manual;
  margin: 0;
  padding-inline-start: var(--sperrung-titel-gross);
  color: var(--text-normal);
  font-family: var(--schrift-titel);
  font-size: var(--grad-titel-gross);
  font-weight: var(--gewicht-fett);
  line-height: var(--zeilen-titel-gross);
  letter-spacing: var(--sperrung-titel-gross);
}
/* Die Projektzeile wie im Entwurf: der Name im Fliesstext, die
   Hochschule darunter im Kleingedruckten, beide im Grau des Entwurfs.
   balance, damit auf 320px „Ein Projekt von / Berrit Schindler" steht
   und nicht der Name ueber zwei Zeilen reisst. */
.auftakt__projekt {
  margin: calc(var(--rhythmus) * .75) 0 0;
  color: var(--text-dim);
  font-size: var(--grad-text);
  line-height: var(--zeilen-text);
  letter-spacing: var(--sperrung-text);
  text-wrap: balance;
}
.auftakt__hochschule {
  display: block;
  font-size: var(--grad-klein);
  line-height: var(--zeilen-klein);
  letter-spacing: var(--sperrung-klein);
}
.auftakt__auge {
  display: block;
  width: 162px;
  height: auto;
  margin-block-start: calc(var(--rhythmus) * 1.5);
}
.auftakt__zaehler {
  margin: calc(var(--rhythmus) * .75) 0 0;
  color: var(--text-dim);
  font-size: var(--grad-klein);
  line-height: var(--zeilen-klein);
  letter-spacing: var(--sperrung-klein);
  font-variant-numeric: lining-nums tabular-nums;
}
.auftakt > .leitfrage { margin-block-start: 0; }
/* Der Pfeil unter der Frage, um anzuzeigen, dass es weiter unten
   weitergeht. --text-faint, die Stufe fuer Ornament: er ist aria-hidden
   und traegt nichts, was die Frage darueber nicht schon sagt — leicht
   durchscheinend, wie im Auftrag gewuenscht, und ohne eigene Farbe.
   Er bewegt sich NICHT: kein Wippen, kein Pulsieren. Auf dieser Seite
   bewegt sich nichts, und ein wippender Pfeil waere die zweite
   Bewegung im ganzen Projekt neben dem Balken der Uhr.

   In Plex Mono und nicht im Fliesstext: Helvetica Neue hat keine Pfeile,
   und jedes Geraet fiele auf eine andere Ersatzschrift zurueck. So holt
   der Browser den kleinen Pi-Teil von Plex (oben) und zeichnet ueberall
   denselben Pfeil — denselben wie an den Raendern der Galerie.

   20px und keine der vier Stufen: der Pfeil ist ein Zeichen, kein Text.
   Im Grad des Fliesstexts ginge er unter der Frage verloren, im Titel
   (24px) waere er lauter als die Frage, auf die er zeigt. */
.auftakt__pfeil {
  display: block;
  margin-block: calc(var(--rhythmus) * .25) calc(var(--rhythmus) * .5);
  color: var(--text-faint);
  font-family: var(--schrift-titel);
  font-size: 20px;
  font-weight: var(--gewicht-fett);
  line-height: 1;
}

/* ─── Desktop: kein Riegel, nur ein Hinweis ───────────────────────
   Erkennung ueber die Faehigkeiten des Zeigegeraets, NIE ueber den
   User-Agent: ein Tablet mit Tastatur, ein Telefon am Monitor und
   jeder kuenftige Formfaktor beantworten pointer/hover richtig und
   eine UA-Liste falsch.

   Der Rechnerblock ist per Vorgabe aus, nicht per Vorgabe an: faellt
   die Medienabfrage aus (altes Geraet, deaktiviertes CSS), sieht der
   Besucher die Umfrage und nicht einen QR-Code ohne Kamera.         */
.rechner { display: none; }
.rechner__code { display: block; width: 180px; height: auto; }

/* ═══ Breakpoints ═══════════════════════════════════════════════════
   Drei Schwellen, dieselben wie in quiet.css, plus die eine fuer den
   Rechner. Die Grade bleiben auf jeder Breite dieselben; nur der
   grosse Titel ist bis 390px kleiner (Tokenblock).
   ═══════════════════════════════════════════════════════════════════ */
@media (min-width: 40em) { :root { --rand-x: 24px; } }
@media (min-width: 48em) { :root { --rand-x: 32px; } }

@media (pointer: fine) and (hover: hover) {
  .rechner { display: block; }
  /* Dieselbe Seite, nicht eine aufgeblasene: 430px ist die Breite
     eines grossen Telefons, und die Umfrage ist fuer diese Breite
     entworfen. Ohne diese Zeile gaelte das Satzmass, 40em bei 12px
     Grundgrad, also 480px — breiter als jedes Telefon, fuer das der
     Entwurf gemacht ist. */
  .spalte { max-width: 430px; }
}
/* Erst ab 56em steht der QR-Code NEBEN der Spalte: 430px Spalte plus
   48px Rinne plus 180px Code sind 658px, darunter wuerde er die
   Spalte schieben. .bahn ist dafuer da und sonst nichts — ohne die
   Abfrage bleibt sie eine gewoehnliche Blockfolge. */
@media (pointer: fine) and (hover: hover) and (min-width: 56em) {
  .spalte { max-width: calc(430px + var(--rhythmus) * 2 + 180px); }
  .bahn {
    display: grid;
    grid-template-columns: 430px minmax(0, 180px);
    column-gap: calc(var(--rhythmus) * 2);
    align-items: start;
  }
}

/* ═══ Bewegung ══════════════════════════════════════════════════════
   Es gibt genau einen Uebergang (color, 140ms) und zwei fortlaufende
   Bewegungen, beide am Balken der Uhr: sein Schrumpfen ueber die
   Laufzeit und sein Puls in den letzten 30 Sekunden.
   ═══════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
  }
  html { scroll-behavior: auto; }
  /* Der Balken wird AUSDRUECKLICH NICHT ausgeblendet: er ist
     Information und keine Dekoration, und wer Bewegung reduziert,
     verliert sonst als Einziger die Restanteilsanzeige. timer.js
     fragt dieselbe Medienabfrage ab und setzt die Breite dann nur
     noch bei jedem Wechsel einer 10-%-Stufe — zehn Spruenge statt
     rund vierhundertachtzig, die Zahl daneben bleibt sekundengenau.

     Der Uebergang von 260ms ist hier schon erledigt und wird NICHT ein
     zweites Mal abgeschaltet: die .01ms-Zeile oben traegt !important
     und gewinnt gegen jede transition-duration. Ein eigenes
     `transition: none` waere eine zweite Regel fuer dieselbe Wirkung,
     und die beiden liefen beim naechsten Umbau auseinander. Bei der
     Animation liegt der Fall anders — siehe die Regel darunter. */
  .uhr__balken { display: block; transform-origin: left; }
  /* Kein Puls. Diese Regel ist Pflicht und nicht etwa durch die
     .01ms-Zeile oben schon erledigt: eine Animation mit `infinite` und
     einer Dauer von .01ms laeuft nicht langsamer, sie laeuft tausendfach
     je Bild und wird bei jedem Neuzeichnen an einer zufaelligen Stelle
     abgetastet. Aus dem ruhigen Puls wuerde dann genau das Flackern,
     das SC 2.3.1 verbietet — die Einstellung, die Bewegung abbestellt,
     haette sie verschlimmert. `animation: none` nimmt den Namen, und
     ohne Namen laeuft keine Dauer.

     Die Zahl wechselt trotzdem auf --dringend-hell: Farbe ist keine
     Bewegung, und die Person soll denselben Hinweis bekommen wie alle
     anderen, nur ohne ihn zappeln zu sehen. */
  .uhr--knapp .uhr__balken { animation: none; opacity: 1; }
}

/* ═══ Druck ═════════════════════════════════════════════════════════
   Gedruckt wird hier realistisch nur /hinweise/ — die DSGVO-Punkte
   zum Abheften. Alles, was den Ablauf bedient, faellt dafuer weg.
   ═══════════════════════════════════════════════════════════════════ */
@media print {
  .uhr, .sprung, .rechner, .knopf, .vorschau { display: none; }
  /* Die Zeichnungen, der Pfeil und der Regler: Zierde und Bedienung, auf
     Papier beides ohne Zweck, und ein rotes Auge auf einem Laserdruck ist
     ein grauer Fleck. */
  .abbildung, .auftakt__auge, .auftakt__pfeil, .titelzeile__bild,
  .zurueck, .regler { display: none; }
  :root {
    /* Vollstaendig, nicht nur die Textstufen: die Vorgabe ist dunkel,
       also muss hier jede Farbe umgedreht werden, die auf Papier sonst
       als schwarze Flaeche herauskaeme — auch die drei Mischungen. */
    --grund: #fff; --text-normal: #000; --text-muted: #333;
    --text-dim: #444; --text-faint: #777;
    --akzent: #000; --akzent-hover: #000; --rahmen: #999;
    /* Die beiden Dringlichkeitstoene auch dann, wenn sie heute nur an
       der Uhr haengen und die hier ohnehin verborgen ist: dieser Block
       dreht jede Farbe um, ausnahmslos, damit eine spaeter hinzukommende
       Regel nicht als satte rote Flaeche aufs Papier geht. */
    --dringend: #000; --dringend-hell: #000;
    --flaeche-alt: #f2f2f2; --leitlinie: #999;
    --akzent-flaeche: #000;
    --flaeche-hover: transparent;
    --pille: transparent; --pille-stark: transparent; --markierung: transparent;
    /* Die Grade fuer Papier. Jede Regel liest ihren Grad aus diesen
       Tokens, ein Grad am body erreichte keinen Text mehr; die
       Sperrungen in em gehen von selbst mit. Am Bildschirm waeren es
       9pt, 18pt und 7,5pt. */
    --grad-text: 11pt; --grad-titel: 16pt; --grad-klein: 9pt;
  }
  .spalte { max-width: none; padding-block-end: 0; }
  .text a::after { content: " (" attr(href) ")"; font-size: .8em; color: #444; }
  .text h2 { break-after: avoid; }
  .text :is(ul, ol, dl) { break-inside: avoid; }
}
