/* ==========================================================================
   completd.app — shared foundation
   Landing page and the public content layer both build on this file.

   HERKUNFT: uebernommen aus dem Design-Projekt "Completd Web" (Datei
   `styles.css` der Landing-Page-Runde), Werte unveraendert. Was darunter
   unter "Ergaenzungen" steht, gab es dort nicht und ist in 1h des Entwurfs
   ausdruecklich als Vorschlag benannt.

   Diese Datei ist die EINZIGE Farbquelle der Weboberflaeche. Ein Template,
   das eine Farbe hart schreibt, ist ein Fehler — dieselbe Regel wie
   Theme.swift in der App (CLAUDE.md, "Farben und Masse nie hart schreiben").
   ========================================================================== */

:root {
  /* --- Colour: dark is the canonical scheme (mirrors the app) ------------- */
  /* **Seit 285 die Palette der App** (Theme.swift, Entwurf 240) — vorher
     stand hier der Stand von vor 240, und Web und App zeigten zwei Violetts.
     Die Namen blieben; nur die Werte folgen `Palette.nocturne`/`.daylight`. */
  --ground:        #0B0C11;
  --surface:       #14161D;
  --chrome:        #08090D;
  --hairline:      #23262F;
  --rule:          #1E212A;
  --row-rule:      #1A1D25;

  --text:          #F2F2F7;
  --text-secondary:#B9B9C4;
  --text-tertiary: #9A9AA6;

  --accent:        #B5ABFC;  /* Knopfflaeche und Linkfarbe, wie in der App */
  --accent-hover:  #CFC7FF;  /* akzentFlaecheText der App */
  --on-accent:     #16122E;  /* onAccentFill der App, 8,8:1 auf dem Akzent */

  --gold:          #D9B84A;  /* reserved: year in review / game of the year */

  /* Gruen und Rot der App (`pos`/`neg`). Im Web nur im Admin-Bereich —
     „erledigt" und „gefaehrlich" (285); vorher standen dort eigene Hexwerte. */
  --pos:           #6FBF8B;
  --neg:           #D0716B;

  --focus:         #B5ABFC;
  --cover-shadow:  0 24px 48px rgba(0, 0, 0, .55);

  /* --- Type -------------------------------------------------------------- */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --step-s:    0.8125rem;  /* fine print, footer            */
  --step-m:    0.9375rem;  /* labels, small copy            */
  --step-0:    1.0625rem;  /* body                          */
  --step-1:    1.1875rem;  /* lead paragraphs               */
  --step-2:    clamp(1.35rem, 1.15rem + 0.9vw, 1.65rem);   /* h3          */
  --step-3:    clamp(1.7rem,  1.35rem + 1.9vw, 2.4rem);    /* h2          */
  --step-4:    clamp(2.1rem,  1.45rem + 3.6vw, 3.35rem);   /* h1          */
  --step-mega: clamp(7.5rem,  24vw, 14rem);                /* the zero    */

  --leading-tight: 1.08;
  --leading-head:  1.18;
  --leading-body:  1.65;

  --measure: 34rem;      /* ≈ 66–68 characters */
  --page:    64rem;

  /* --- Space / shape ----------------------------------------------------- */
  --gap-1: .375rem;
  --gap-2: .75rem;
  --gap-3: 1.25rem;
  --gap-4: 2rem;
  --gap-5: 3rem;
  --section-y: clamp(4.5rem, 10vw, 7.5rem);

  /* **Der vertikale Rhythmus des Entwurfs** (A0.1, Entscheidung 237).
     Vier Werte, und jeder hat einen Anlass: 80 fuer einen Abschnitt mit Bild,
     64 fuer einen reinen Textabschnitt, 56 fuer den Einstieg auf Presse und
     Changelog, 44 fuer den Kopfblock. Vorher gab es genau einen (`--section-y`),
     und damit sah ein Satz in einer Spalte so gewichtig aus wie das Regalbild.
     `clamp` nach unten, weil 88 pt Seitenrand auf einem Telefon die halbe
     Breite waeren. */
  --sec-full:  clamp(3.5rem, 8vw, 5rem);     /* 80px */
  --sec-text:  clamp(3rem,   6vw, 4rem);     /* 64px */
  --sec-intro: clamp(2.5rem, 5vw, 3.5rem);   /* 56px */
  --sec-head:  clamp(2rem,   4vw, 2.75rem);  /* 44px */
  --pad-x:     clamp(1.25rem, 7vw, 5.5rem);  /* 88px ab ~1260px Breite */

  /* Die Linkfarbe. Bis 285 war `--accent` ein dunkleres Violett (#9184D9,
     4,2:1 auf dem Grund) und `--link` der hellere Schritt; seit der App-Palette
     sind beide derselbe Wert, 9,5:1. Der Name bleibt, weil er die Rolle sagt. */
  --link: #B5ABFC;
  --radius:    12px;      /* same as the app's covers */
  --radius-s:  8px;

  /* --- Ergaenzungen fuer die Weboberflaeche (Entwurf 1h) ------------------ */
  /* Der App-Streifen: getoente Flaeche mit Oberlinie. Als eigene Tokens und
     nicht als `color-mix()` im Baustein, damit der helle Modus einen anderen
     Deckungsgrad bekommen kann — 8 % eines dunklen Akzents auf hellem Grund
     ist fast unsichtbar. */
  --accent-wash: rgba(181, 171, 252, .12);  /* akzentFlaeche der App */
  --accent-line: rgba(181, 171, 252, .30);  /* akzentRahmen der App */
  /* Der leere Stern. Lag zwischen den vorhandenen Grautoenen: --text-tertiary
     ist zu hell (liest sich als halber Stern), --hairline zu dunkel. */
  --star-empty:  #544F73;  /* leererStern der App */
  /* Die zweite Flaeche der Landing Page, im Wechsel mit `--ground` (274). */
  --band:        #14161D;
  /* Die Fugen der Kartenraster auf der Presseseite (276). `--hairline`
     hebt sich von `--surface` dunkel nur um 1,3:1 ab — als Trennlinie
     zwischen Karten war sie auf dem Bildschirm nicht zu sehen. */
  --seam:        #3A3D49;
}

@media (prefers-color-scheme: light) {
  :root {
    --ground:        #F7F6F3;
    --surface:       #FFFFFF;
    --chrome:        #FFFFFF;
    --hairline:      #E7E5E1;
    --rule:          #E9E7E3;
    --row-rule:      #EEECE8;

    --text:          #17161D;
    --text-secondary:#4E4D5A;
    --text-tertiary: #5F5E6C;

    --accent:        #5747C9;
    --accent-hover:  #4234A8;
    --on-accent:     #ECEAFB;

    /* **Seit 286 auch der Wert der App.** Das fruehere helle Gold (#C9A94F)
       mass auf dem Grund 2,1:1; hier steht Gold als Text
       (`.year .label`, `.chapter--gold`) und braucht AA — auch auf `--band`
       (#EDEAE4), wo das bisherige #8A6A12 nur 4,2:1 erreicht: #82640F misst
       dort 4,6:1 und auf dem Grund 5,1:1. */
    --gold:          #82640F;
    --pos:           #237F4E;  /* 4,6:1 auf dem Grund */
    --neg:           #B5534D;  /* 4,5:1 auf dem Grund */

    --focus:         #5747C9;
    --cover-shadow:  0 18px 36px rgba(16, 17, 24, .16);

    --accent-wash: rgba(87, 71, 201, .09);
    --accent-line: rgba(87, 71, 201, .26);
    --star-empty:  #C4C0B9;
    --band:        #EDEAE4;  /* alt der App */
    --seam:        #D3D5DD;
    /* **Bis 276 nur dunkel definiert**: hell stand `#B5ABFC` auf Weiss,
       2,06:1 — die Kopier-Knoepfe und Download-Links der Presseseite und die
       Marken im Changelog lagen unter AA. Der Akzent misst 6,2:1. */
    --link:        #5747C9;
  }
}

/* --- Reset ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font: var(--step-0)/var(--leading-body) var(--font-sans);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}
body > main { flex: 1; }
img, picture, video { display: block; max-width: 100%; height: auto; }
h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.021em; }
h1 { font-size: var(--step-4); line-height: var(--leading-tight); letter-spacing: -0.03em; }
h2 { font-size: var(--step-3); line-height: var(--leading-head); }
h3 { font-size: var(--step-2); line-height: var(--leading-head); }
p  { margin: 0; }
a  { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: .2em; }
a:hover { color: var(--accent-hover); }
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: 4px;
}
::selection { background: var(--accent); color: var(--on-accent); }

/* --- Layout primitives ---------------------------------------------------- */
.wrap { width: 100%; max-width: var(--page); margin-inline: auto; padding-inline: var(--pad-x); }
.measure { max-width: var(--measure); }
.stack > * + * { margin-top: var(--gap-3); }
.section { padding-block: var(--section-y); border-top: 1px solid var(--rule); }
.section--flush { border-top: 0; }

.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: .95em; letter-spacing: -0.01em; }
.label {
  font-size: var(--step-m); font-weight: 500; color: var(--text-tertiary);
  text-transform: uppercase; letter-spacing: .09em;
}
.lead { font-size: var(--step-1); color: var(--text-secondary); }
.fine { font-size: var(--step-s); color: var(--text-tertiary); line-height: 1.55; }

.skip {
  position: absolute; left: -9999px; top: 0;
  padding: .625rem 1rem; background: var(--surface); color: var(--text);
  border: 1px solid var(--hairline); border-radius: var(--radius-s); z-index: 10;
}
.skip:focus { left: 1rem; top: 1rem; }

/* --- Header --------------------------------------------------------------- */
/* **12px vertikal, 88px horizontal, eigener Grund, Haarlinie unten** (A3).
   Der Grund ist `--chrome` und nicht `--ground`: die Leiste soll sich vom
   Blatt abheben, ohne einen Schatten zu brauchen — der Entwurf erlaubt
   ausser den beiden Hintergruenden keine Dekoration. */
.site-head { background: var(--chrome); border-bottom: 1px solid var(--rule); }
.site-head-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--gap-3);
  padding-block: .75rem;
}
.head-right { display: flex; align-items: center; gap: var(--gap-3); }
/* **44px hoch wie jeder andere Griff** (A0.5). Die Wortmarke ist der einzige
   Weg zurueck auf die Startseite und traf 28 Pixel hoch. `align-items:
   center` statt `baseline`, weil eine Mindesthoehe die Grundlinie sonst
   nach oben schiebt. */
.wordmark {
  display: inline-flex; align-items: center; gap: 0; min-height: 44px;
  font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.02em;
  color: var(--text); text-decoration: none;
}
.wordmark span { color: var(--accent); }
.wordmark:hover { color: var(--text); }
/* Die Haarlinie sitzt jetzt an der Leiste selbst; der Block bleibt leer,
   damit keine Seite ihn einzeln abschalten muss. */
.head-rule { height: 0; }

/* --- Footer --------------------------------------------------------------- */
.site-foot { border-top: 1px solid var(--rule); padding-block: 2rem; }
.foot-links { display: flex; flex-wrap: wrap; gap: var(--gap-2) var(--gap-4); margin: 0; padding: 0; list-style: none; }
/* **44px Trefferflaeche auch hier** (A0.5). Ein Fusszeilenlink ist der
   kleinste Knopf der Seite und traf vorher knapp 20 Pixel hoch. */
.foot-links a { font-size: var(--step-m); display: inline-flex; align-items: center; min-height: 44px; }
.site-foot .fine { margin-top: var(--gap-3); max-width: var(--measure); }

/* --- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: .8rem 1.4rem;
  background: var(--accent); color: var(--on-accent);
  font: 500 var(--step-0)/1 var(--font-sans); letter-spacing: -0.01em;
  border: 0; border-radius: var(--radius); text-decoration: none; cursor: pointer;
}
.btn:hover { background: var(--accent-hover); color: var(--on-accent); }

/* --- Der App-Streifen ----------------------------------------------------- */
/* Ein normaler Abschnitt im Fluss, direkt ueber der Fussleiste, auf jeder
   Seite gleich. Ein Satz, ein Knopf, kein zweiter Anlauf. */
.app-strip {
  background: var(--accent-wash);
  border-top: 1px solid var(--accent-line);
  padding-block: var(--gap-4);
}
.app-strip p { max-width: var(--measure); }
.app-strip .btn { margin-top: var(--gap-3); }

/* --- Cover ---------------------------------------------------------------- */
.cover-stage { display: flex; justify-content: center; padding-top: var(--gap-3); }
.cover {
  width: 210px; max-width: 60vw; aspect-ratio: 3 / 4;
  border-radius: var(--radius); box-shadow: var(--cover-shadow);
  object-fit: cover; background: var(--surface);
}

/* --- Sterne ---------------------------------------------------------------- */
/* Zwei uebereinanderliegende Reihen: die untere leer, die obere per Breite
   beschnitten. Damit ist jede halbe Stufe darstellbar, ohne ein
   Halbstern-Zeichen zu brauchen — und ohne JavaScript. */
.stars {
  position: relative; display: inline-block; white-space: nowrap;
  letter-spacing: .08em; font-size: var(--step-1); color: var(--star-empty);
}
.stars-fill {
  position: absolute; inset-block: 0; left: 0;
  overflow: hidden; color: var(--text);
}
.star-line { margin-top: var(--gap-2); }
.star-line .stars { font-size: var(--step-s); }
.rating-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--gap-2); }
.rating-row .num { font-size: var(--step-1); color: var(--text); }

/* Ein Inhaltsabschnitt, nicht ein Landing-Page-Abschnitt.
   `.section` traegt --section-y (4,5-7,5rem) — richtig fuer eine Seite, die
   aus grossen Kapiteln besteht, viel zu viel fuer „Titel, Wertung, drei
   Rezensionen". Der Entwurf zeigt 26 px ueber der Oberlinie. */
.block { margin-top: var(--gap-4); padding-top: var(--gap-3); border-top: 1px solid var(--rule); }
.block > .label + * { margin-top: var(--gap-3); }

/* --- Rezensionen ----------------------------------------------------------- */
.review + .review { margin-top: var(--gap-3); padding-top: var(--gap-3); border-top: 1px solid var(--row-rule); }
.review-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--gap-2); }
.review-head .who { font-size: var(--step-m); font-weight: 500; color: var(--text); }
.review-head .stars { font-size: var(--step-s); }
.review-head .when { font-family: var(--font-mono); font-size: var(--step-s); color: var(--text-tertiary); }
.review-text { margin-top: .5625rem; color: var(--text-secondary); }

/* Die Spoiler- und Leerzustands-Kachel. Sichtbar *etwas anderes* als eine
   Rezension — und der Text ist serverseitig nicht in der Antwort, es gibt
   also nichts, was die Entwicklerkonsole freilegen koennte. */
.tile {
  margin-top: .6875rem; padding: 1.125rem;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius);
}
.tile p + p { margin-top: .4375rem; }

/* --- Landing Page (Entscheidung 191) --------------------------------------
   Woertlich aus `styles.css` des Design-Projekts uebernommen. Steht in
   derselben Datei wie Spiel-, Listen- und Profilseite, weil alle vier
   dasselbe `base.html` benutzen — zwei Stylesheets waeren zwei Orte, an denen
   ein Token auseinanderlaufen kann. */

/* **44x44 je Pille** (A0.5, Entscheidung 237). Hier stand `.3rem .1rem` —
   eine Trefferflaeche von rund 20x24 Pixeln fuer den einzigen Umschalter der
   Seite. Der Entwurf sagt es unmissverstaendlich: „This is a marketing site
   with one form; there is no excuse for a target under 44px." */
.langs { display: flex; align-items: center; gap: 2px; font-size: var(--step-m); }
.langs a, .langs [aria-current] {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
  text-decoration: none; color: var(--text-tertiary);
  letter-spacing: .04em; text-transform: uppercase;
}
.langs a:hover { color: var(--text); }
.langs [aria-current="true"] { color: var(--text); font-weight: 500; }

.btn--quiet {
  background: transparent; color: var(--text);
  border: 1px solid var(--hairline);
}
.btn--quiet:hover { background: var(--surface); color: var(--text); }

/* **Hinter `.btn` und `.langs`, nicht davor** (274): gleiche Spezifitaet,
   also gewinnt die spaetere Regel. Der Block stand bei der Kopfzeile, vor
   `.btn` — dessen Polsterung und 48px schlugen ihn, und `.btn--head` hat auf
   Presse und Changelog nie gewirkt.

   40px Hoehe, 10px Radius, 1px Rand — die Kopfzeilenfassung des Knopfs. Sie
   ist flacher als der Knopf im Fliesstext (48px) und bleibt trotzdem ueber
   der Trefferflaeche, weil die Leiste ihn oben und unten mitpolstert. */
.btn--head { min-height: 40px; padding-inline: 1rem; border-radius: 10px; font-size: var(--step-m); white-space: nowrap; }
.head-cta-short { display: none; }
/* **Handybreite** (274). Wortmarke, drei Sprachpillen zu 44 px und ein Knopf
   brauchten bei 375 px rund 400 px. Drei Dinge geben nach, keines davon die
   Trefferflaeche: die Pille der Sprache, auf der man schon ist (ein Link auf
   die eigene Seite), die Luecken, und die Beschriftung des Knopfs. Der Knopf
   selbst bleibt 44 px hoch — hier ist die Leiste flacher gepolstert. */
@media (max-width: 30rem) {
  .site-head-row { gap: var(--gap-2); }
  .head-right { gap: .25rem; }
  .langs [aria-current="true"] { display: none; }
  .btn--head { min-height: 44px; padding-inline: .75rem; }
  .head-cta-long { display: none; }
  .head-cta-short { display: inline; }
}

/* --- Hero ----------------------------------------------------------------- */
.hero { padding-block: clamp(2.5rem, 6vw, 4.5rem) var(--section-y); }
.hero-grid { display: grid; gap: clamp(2.5rem, 6vw, 4rem); align-items: center; }
.hero p.lead { max-width: var(--measure); }
.hero-cta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-3); margin-top: var(--gap-4); }
.hero-shot { justify-self: center; width: min(100%, 310px); }
@media (min-width: 60rem) {
  .hero-grid { grid-template-columns: minmax(0, 1fr) 310px; }
  .hero-shot { width: 310px; }
}

/* --- Figures -------------------------------------------------------------- */
.figure { margin: var(--gap-5) 0 0; }
.figure img { border-radius: var(--radius); box-shadow: var(--cover-shadow); }
.figure--device img { box-shadow: none; }
/* Ein freigestelltes Bild (Entscheidung 226): kein Rechteck, also weder
   Rundung noch Schatten — beides braucht eine Kante, die es hier nicht gibt.
   Ein Schatten auf einer freigestellten Form saehe aus wie ein Halo, und
   eine Rundung schnitte Ecken von etwas ab, das schon keine hat. */
.figure--cutout img { box-shadow: none; border-radius: 0; }
.figure figcaption { margin-top: var(--gap-2); }
.figure--wide { max-width: 42rem; }
/* So breit wie die Textspalte darueber (Entscheidung 226). Ein Screenshot,
   der ueber den Satz hinausragt, den er belegt, liest sich wie ein zweiter
   Abschnitt statt wie seine Abbildung. */
.figure--measure { max-width: var(--measure); }
.figure--tall { max-width: 22.5rem; }

/* Platzhalter fuer den Wisch-Clip, bis das MP4 da ist. */
.slot {
  display: grid; place-items: center; gap: var(--gap-1);
  aspect-ratio: 16 / 10; max-width: 42rem;
  background: var(--surface); border: 1px dashed var(--hairline);
  border-radius: var(--radius); color: var(--text-tertiary);
  padding: var(--gap-3); text-align: center;
}

/* --- Signup --------------------------------------------------------------- */
.signup {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 4vw, 2.5rem);
  max-width: 38rem;
}
.signup h2 { max-width: 22ch; }
.form-row { display: grid; gap: var(--gap-2); margin-top: var(--gap-4); }
@media (min-width: 34rem) { .form-row { grid-template-columns: 1fr auto; align-items: end; } }
.field { display: grid; gap: .4rem; }
.field label { font-size: var(--step-m); color: var(--text-secondary); }
.field input {
  min-height: 48px; width: 100%;
  padding: .7rem .875rem;
  background: var(--ground); color: var(--text);
  font: var(--step-0)/1.4 var(--font-sans);
  border: 1px solid var(--hairline); border-radius: var(--radius);
}
.field input::placeholder { color: var(--text-tertiary); }
.signup .fine { margin-top: var(--gap-3); }
.form-note { margin-top: var(--gap-3); font-size: var(--step-m); line-height: 1.5; }
.form-note:empty { display: none; }
.form-note[data-state="ok"]    { color: var(--text); }
.form-note[data-state="error"] { color: var(--text); }
.form-note[data-state="error"] strong { color: var(--accent); font-weight: 500; }

/* Der Honigtopf aus Entscheidung 182. `position:absolute` statt
   `display:none`: ein Feld, das gar nicht im Layout liegt, fuellen manche
   Bots trotzdem — eines, das `display:none` traegt, ueberspringen die
   besseren. `aria-hidden` und `tabindex=-1` halten es von Menschen fern. */
.trap {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden;
}

/* --- The zero ------------------------------------------------------------- */
.zero {
  margin-top: var(--gap-5);
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: clamp(2rem, 6vw, 4rem) clamp(1.25rem, 5vw, 3rem);
  text-align: center;
}
.zero b {
  display: block;
  font: 300 var(--step-mega)/0.82 var(--font-mono);
  letter-spacing: -0.06em; color: var(--text);
  font-variant-numeric: tabular-nums slashed-zero;
}
.zero em {
  display: block; margin-top: var(--gap-3);
  font: 500 var(--step-m)/1.4 var(--font-sans); font-style: normal;
  text-transform: uppercase; letter-spacing: .16em; color: var(--text-tertiary);
}

/* --- Quiet section (limits) ---------------------------------------------- */
.quiet { color: var(--text-secondary); }
.quiet h2 { font-size: var(--step-2); color: var(--text); }

/* --- Year in review ------------------------------------------------------- */
.year .label { color: var(--gold); }
.year-grid { display: grid; gap: clamp(2rem, 5vw, 3.5rem); align-items: start; }
@media (min-width: 56rem) { .year-grid { grid-template-columns: minmax(0, 1fr) 22.5rem; } }
.year-grid .figure { margin-top: 0; justify-self: center; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

/* --- Desktop (Entwurf 1e) --------------------------------------------------
   „Am Desktop waechst nur die Buehne, nicht die Struktur": --page 64rem
   zentriert, Cover 300 px in der linken Spalte, Text weiter auf --measure —
   Rezensionen laufen nie ueber 68 Zeichen. Der App-Streifen wird einzeilig
   und legt den Knopf nach rechts. */
@media (min-width: 60rem) {
  .game-grid {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 3.5rem);
    align-items: start;
  }
  .game-grid > .cover-stage { position: sticky; top: var(--gap-4); padding-top: 0; }
  .game-grid .cover { width: 300px; max-width: 100%; }
  .game-body { max-width: var(--measure); }
  .app-strip .wrap {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--gap-4);
  }
  .app-strip .btn { margin-top: 0; flex: none; }
}

/* --- Liste und Profil (Phase 2b, Entwuerfe 2a-2f) -------------------------- */

.page-head { padding-block: var(--gap-4) 0; max-width: var(--measure); }
.page-head .label + h1 { margin-top: var(--gap-2); }

/* Von uns / von Nutzern: eine helle 1-px-Oberlinie plus C/ in mono. Kein
   Abzeichen in Farbe, kein Logo, keine Auszeichnung im Titel. */
.page-head--curated { border-top: 1px solid var(--text-tertiary); padding-top: var(--gap-3); }
.mark { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0; }

/* Ein privates oder aus dem Web abgemeldetes Konto behaelt seinen Namen,
   verliert aber die Verlinkung — ein Link auf eine 404 verriete, dass es dort
   jemanden gibt. */
.owner-quiet { color: var(--text-secondary); }

.cover-blank { display: block; width: 100%; aspect-ratio: 3 / 4;
  background: var(--surface); border-radius: var(--radius-s); }

/* --- Zeilenliste (mit Begruendungssaetzen) -------------------------------- */
.rows { list-style: none; margin: var(--gap-4) 0 0; padding: 0; }
.row { display: flex; gap: var(--gap-3); padding-block: var(--gap-3); }
.row + .row { border-top: 1px solid var(--row-rule); }
.row-cover { flex: none; width: 74px; }
.row-cover img { width: 74px; border-radius: var(--radius-s); box-shadow: var(--cover-shadow); }
.row-body { min-width: 0; max-width: var(--measure); }
.row-title { color: var(--text); text-decoration: none; font-weight: 500; }
.row-title:hover { color: var(--accent); }
.row-meta { margin-top: .25rem; font-size: var(--step-s); color: var(--text-tertiary); }
.row-note { margin-top: .5rem; color: var(--text-secondary); }

/* --- Raster (ohne Saetze) ------------------------------------------------- */
.grid {
  list-style: none; margin: var(--gap-4) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-3) var(--gap-3);
}
.grid-cover { width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: var(--radius-s); box-shadow: var(--cover-shadow); }
.grid-title { margin-top: var(--gap-2); font-size: var(--step-m); color: var(--text-secondary); }
.more { margin-top: var(--gap-4); }

/* --- Profil ---------------------------------------------------------------- */
.person { display: flex; align-items: center; gap: var(--gap-3); }
.avatar { width: 72px; height: 72px; flex: none; border-radius: 50%; object-fit: cover; }
.avatar--blank {
  display: grid; place-items: center;
  background: var(--row-rule); color: var(--text-secondary);
  font: 500 1.5rem/1 var(--font-sans);
}
.bio { margin-top: var(--gap-4); }

/* Drei Zahlen zwischen zwei Regeln, gleiche Spaltenbreite. Kein Punktestand. */
.figures {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-3); margin: var(--gap-4) 0 0; padding-block: var(--gap-3);
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  max-width: var(--measure);
}
.figures dt { text-transform: uppercase; letter-spacing: .09em; }
.figures dd { margin: .25rem 0 0; font-size: var(--step-3); color: var(--text); }

/* Cover plus Sterne, keine Titel. Das vierte Cover ist angeschnitten — das
   sagt, dass es weitergeht, ohne einen Knopf dafuer zu brauchen. */
.rated-row {
  list-style: none; margin: var(--gap-3) 0 0; padding: 0 0 var(--gap-2);
  display: grid; grid-auto-flow: column; grid-auto-columns: 104px;
  gap: var(--gap-3); overflow-x: auto; overscroll-behavior-x: contain;
}
.rated-row img, .rated-row .cover-blank {
  width: 104px; aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: var(--radius-s); box-shadow: var(--cover-shadow);
}


.list-links { list-style: none; margin: var(--gap-3) 0 0; padding: 0; max-width: var(--measure); }
.list-links li {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--gap-3); padding-block: var(--gap-2);
}
.list-links li + li { border-top: 1px solid var(--row-rule); }

@media (min-width: 60rem) {
  .grid { grid-template-columns: repeat(3, 1fr); max-width: 44rem; }
  .rated-row { grid-auto-columns: 128px; }
  .rated-row img, .rated-row .cover-blank { width: 128px; }
}

/* --- Jahresrueckblick unter /wrap/{token} (Entwurf 1f/1g) ------------------
   Jedes Kapitel ist ein Bildschirm. Keine Scroll-Animationen — die Vorgabe der
   Landing Page gilt auch hier, das Snappen selbst ist die einzige Bewegung. */

.who-link { font-size: var(--step-m); }
.who-quiet { font-size: var(--step-m); color: var(--text-secondary); }

.wrap-deck {
  scroll-snap-type: y mandatory;
  overflow-y: auto;
  height: 100svh;
}
/* `body` ist ein Flex-Container mit Kopf und Fuss; das Deck bekommt den Rest
   und scrollt in sich, damit die Kopfzeile nicht mitwandert. */
body:has(.wrap-deck) { height: 100svh; overflow: hidden; }
body:has(.wrap-deck) > main { min-height: 0; }
body:has(.wrap-deck) > .site-foot { display: none; }

.chapter {
  scroll-snap-align: start;
  min-height: 100%;
  display: grid;
  align-items: center;
  padding-block: var(--gap-5);
}
.chapter + .chapter { border-top: 1px solid var(--rule); }
.chapter-body { width: 100%; max-width: var(--measure); }
.chapter .label { margin-bottom: var(--gap-2); }

/* Kapitel 1 — die Zahl. Im Hellen steht sie auf --surface mit Haarlinie und
   nicht auf dem Seitengrund: grosse Flaechen kippen dort sonst ins Grelle. */
.big-number { margin-top: 0; }

/* Kapitel 2 — zwoelf Balken. --hairline als Balken, --accent fuer den
   Spitzenmonat: bestehende Werte in neuer Rolle, keine neue Farbe. */
.bars {
  display: grid; grid-template-columns: repeat(12, 1fr);
  gap: 6px; align-items: end;
  height: 190px; margin: var(--gap-4) 0 var(--gap-3);
}
.bar { display: flex; flex-direction: column; justify-content: flex-end; height: 100%; gap: 8px; }
.bar span { display: block; background: var(--hairline); border-radius: 3px; min-height: 2px; }
.bar--peak span { background: var(--accent); }
.bar i {
  font-style: normal; text-align: center;
  font: 500 var(--step-s)/1 var(--font-mono); color: var(--text-tertiary);
}
.bar--peak i { color: var(--text); }

/* Kapitel 3 — das Coverraster, direkt von images.igdb.com. */
.cover-grid {
  list-style: none; margin: var(--gap-4) 0 var(--gap-3); padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(58px, 1fr));
  gap: var(--gap-2);
}
.cover-grid img, .cover-grid .cover-blank {
  width: 100%; aspect-ratio: 3 / 4; object-fit: cover; border-radius: 6px;
}

/* Kapitel 4 — die einzige Stelle mit Gold, im ganzen Web-Teil.
   Dreimal: das Label, die Sterne, die Haarlinie um das Cover. */
.chapter--gold .label { color: var(--gold); }
.chapter--gold .stars .stars-fill { color: var(--gold); }
.goty { display: flex; gap: var(--gap-3); align-items: flex-start; margin-top: var(--gap-3); }
.goty-cover {
  width: 132px; flex: none; border-radius: var(--radius);
  box-shadow: var(--cover-shadow), 0 0 0 1px var(--gold);
}
.quote { margin-top: var(--gap-3); color: var(--text-secondary); }

/* Kapitel 6 — die Randnotizen, auch die unschmeichelhaften. */
.notes { display: grid; gap: var(--gap-3); margin-top: var(--gap-4); }
.note { padding-top: var(--gap-3); border-top: 1px solid var(--row-rule); }
.note p + p { margin-top: .25rem; }

@media (min-width: 60rem) {
  .chapter-body { max-width: 42rem; }
  .bars { height: 240px; }
  .goty-cover { width: 180px; }
}

/* Die Sprechblase am Monatsbalken (Entscheidung 192).
   Auf Zeiger *und* Tastatur *und* Tippen — deshalb ist der Balken ein Knopf
   und die Regel haengt an `:hover` und `:focus-visible` zugleich. */
.bar {
  position: relative;
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
  -webkit-tap-highlight-color: transparent;
}
.bar .tip {
  position: absolute; bottom: calc(100% + 8px); left: 50%; translate: -50% 0;
  z-index: 2; white-space: nowrap; pointer-events: none;
  padding: .3rem .55rem; border-radius: var(--radius-s);
  background: var(--surface); color: var(--text);
  border: 1px solid var(--hairline); box-shadow: var(--cover-shadow);
  font: 500 var(--step-s)/1.2 var(--font-sans);
  opacity: 0; transition: opacity .12s ease;
}
/* **`:focus`, nicht `:focus-visible`.** `:focus-visible` ist eine Heuristik
   des Browsers dafuer, ob eine Fokusanzeige *noetig* ist — und bei einem Tap
   auf dem Telefon entscheidet iOS-Safari regelmaessig „nein". Genau dort wird
   diese Seite aber vor allem gelesen: sie kommt als geteilter Link an. Mit
   `:focus` erscheint die Sprechblase beim Antippen und bleibt stehen, bis
   woanders hingetippt wird — auf einem Zeigergeraet tut `:hover` dasselbe
   ohne Klick. */
.bar:hover .tip, .bar:focus .tip { opacity: 1; }
.bar:focus { outline: none; }
.bar:focus span { background: var(--accent-hover); }
.bar--peak:focus span { background: var(--accent); }
/* Die Tastatur bekommt trotzdem eine sichtbare Anzeige — `:focus` hat oben
   nur die Umrandung abgeschaltet, nicht die Erreichbarkeit. */
.bar:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 4px; }
.bar:hover span { background: var(--accent-hover); }
/* Der Spitzenmonat behaelt seine Farbe auch beim Ueberfahren. */
.bar--peak:hover span { background: var(--accent); }
@media (prefers-reduced-motion: reduce) { .bar .tip { transition: none; } }

/* Die Bibliothek auf der Profilseite (Entscheidung 213).
   Ein Raster, das sich der Breite anpasst — feste Spaltenzahlen brechen auf
   dem einen Geraet, das man nicht getestet hat. */
.covers {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
  gap: var(--gap-3, 12px); list-style: none; padding: 0; margin: 0;
}
.covers img {
  width: 100%; height: auto; aspect-ratio: 3 / 4;
  object-fit: cover; border-radius: 6px; display: block;
}
.cover--blank {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 3 / 4; border-radius: 6px; padding: 6px;
  background: var(--row-rule, #22232c); color: var(--text-secondary, #9498ac);
  font-size: .7rem; text-align: center; overflow: hidden;
}

/* --- Vorschau der Beispiel-Liste auf der Landing Page (Entscheidung 221) --- */
/* Die ganze Kachel ist der Link — ein „ansehen ›" daneben waere ein zweites
   Ziel fuer dieselbe Handlung. Die Cover scrollen waagerecht, statt zu
   schrumpfen: ein Cover unter 60 px ist kein Bild mehr, sondern ein Fleck. */
.list-teaser {
  display: block; margin-top: var(--gap-4);
  padding: var(--gap-3); text-decoration: none;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius);
}
.list-teaser:hover { border-color: var(--accent-line); }
.list-teaser-covers {
  display: flex; gap: var(--gap-2);
  overflow-x: auto; overscroll-behavior-x: contain;
  padding-bottom: var(--gap-2);
}
.list-teaser-covers img {
  flex: none; width: 74px; height: auto;
  border-radius: var(--radius-s); box-shadow: var(--cover-shadow);
}
.list-teaser-line { display: flex; flex-wrap: wrap; gap: var(--gap-2); align-items: baseline; }
.list-teaser-line b { color: var(--text); font-weight: 500; }
.list-teaser-line em { color: var(--text-secondary); font-style: normal; font-size: var(--step-m); }

/* Mehrere Beispiel-Listen untereinander (Entscheidung 225). Abstand zwischen
   ihnen, nicht nur ueber der ersten — sonst kleben zwei Kacheln aneinander
   und lesen sich wie eine. */
.list-teaser + .list-teaser { margin-top: var(--gap-3); }

/* --- Presseseite und Changelog (Entwurf 7) --------------------------------
   Drei Klassen, und keine mehr: alles andere auf beiden Seiten kommt aus dem
   Bestand (`.label`, `.lead`, `.note`, `.quote`, `.fine`). Sie stehen hier
   und nicht als `style`-Attribut in der Vorlage — dieses Stylesheet ist die
   einzige Farbquelle der Weboberflaeche, und eine Ausnahme davon ist der
   Anfang von zwei Wahrheiten ueber dieselbe Farbe. */

/* Die Marke neben einer Version („First external build"). Umrissen und nicht
   gefuellt: sie ordnet ein und ist keine Handlung — gefuellte Flaechen sind
   auf diesen Seiten den Knoepfen vorbehalten.

   **Der Name traegt „release-" davor, und das ist kein Geschmack.** Der
   Admin-Bereich hat eine Klasse desselben kurzen Namens; beide Stylesheets
   werden auf derselben Domain ausgeliefert, und
   `test_keine_klasse_kollidiert_mit_dem_oeffentlichen_stylesheet` haelt sie
   auseinander. Er hat den Namen abgefangen, bevor er deployt war — und beim
   zweiten Anlauf gleich noch einmal, weil der kurze Name in diesem Kommentar
   stand: der Waechter liest die Datei und nicht nur ihre Regeln, was hier
   richtig ist. Ein Klassenname in einem Kommentar ist einer, den jemand
   spaeter benutzt. */
.release-tag {
  display: inline-block; margin-left: var(--gap-2);
  padding: .1rem .4rem; border: 1px solid var(--hairline);
  border-radius: var(--radius-s);
  font-size: var(--step-s); letter-spacing: .06em; color: var(--text-tertiary);
}

/* --- Landing Page, ueberarbeitet (Entwurf 6) ------------------------------

   **Der Takt.** Die Seite hatte achtmal dieselbe Oberlinie: jeder Abschnitt
   begann mit `border-top`, und dadurch klang keiner lauter als ein anderer.
   Zwei Abschnitte stehen jetzt stattdessen auf einer Flaeche — was sie nicht
   *lauter* macht, sondern **anders**, und das ist der Unterschied, den ein
   Rhythmus braucht.

   Es sind genau zwei, und zwar die beiden, die von der Sache handeln statt
   vom Produkt: was die App nicht kann, und wer sie baut. Ein drittes
   Vorkommen waere wieder ein Muster. */
.section--surface {
  border-top: 0;
  background: var(--surface);
}
/* **Die Flaeche traegt kein `wrap`, sie enthaelt eines.**
   Der erste Anlauf legte den Vollbreiten-Trick (`margin-inline: calc(50% -
   50vw)`) auf dasselbe Element, das schon `.wrap` trug — und `.wrap`
   zentriert ueber `max-width` plus `margin-inline: auto`. Beides zusammen
   hebt die Zentrierung auf: der Text stand am linken Bildschirmrand, der
   naechste Abschnitt daneben. Auf dem Bildschirm sofort zu sehen, im
   Quelltext nicht.
   Der Abschnitt ist jetzt der volle Streifen, das `.wrap` darin die Spalte. */
.section--surface > .wrap { padding-block: 0; }

/* Die Fragenliste — die erste Stelle der Seite mit einer dritten Ebene. */
.qa + .qa { margin-top: var(--gap-4); border-top: 1px solid var(--row-rule); padding-top: var(--gap-3); }
.qa h3 { font-size: var(--step-1); font-weight: 500; color: var(--text); margin: 0; }
.qa p { margin-top: .35rem; }

/* Die haftende Kopfzeile — **nur auf der Landing Page** (Entwurf 6).
   Auf einer Spielseite, die jemand ueber einen geteilten Link liest, waere
   eine mitlaufende Leiste mit Anmeldeknopf eine Werbeflaeche ueber dem
   Inhalt. Hier ist der Knopf der Zweck der Seite.

   `backdrop-filter` mit einer halbdurchsichtigen Flaeche und **einem
   deckenden Rueckfall davor**: wo der Filter fehlt (aeltere Browser, oder
   abgeschaltet), stuende sonst der Seiteninhalt lesbar durch die Leiste. */
.site-head--sticky {
  position: sticky; top: 0; z-index: 10;
  background: var(--chrome);
  border-bottom: 1px solid var(--rule);
}
@supports (backdrop-filter: blur(1px)) {
  .site-head--sticky {
    background: color-mix(in srgb, var(--chrome) 86%, transparent);
    backdrop-filter: blur(12px);
  }
}


/* ==========================================================================
   Die drei Marketingseiten (Entwurf A, Entscheidung 237)
   ==========================================================================
   **Ein System, drei Seiten.** Landing Page, Presse und Changelog teilen
   Kopfzeile, Fusszeile, Rhythmus und Palette; was hier steht, gilt fuer alle
   drei. Der Entwurf nennt den Grund fuer die Trennung von allem darueber:
   „This is one visual system across three pages, not three designs."

   **Zwei Hintergruende, nicht acht.** `--ground` fuer das Blatt, `--surface`
   fuer die beiden vollbreiten Abschnitte (Regal, Jahresrueckblick). Keine
   Karten auf Karten, keine Verlaeufe, keine Schatten ausser den benannten.
   Wer hier einen dritten Hintergrund einfuehrt, nimmt den beiden ihre
   Bedeutung. */

/* --- Rhythmus ------------------------------------------------------------- */
.sec       { padding-block: var(--sec-full); }
.sec--text { padding-block: var(--sec-text); }
.sec--alt  { padding-block: var(--sec-full); background: var(--surface); }
.sec--intro{ padding-block: var(--sec-intro) var(--sec-head); }
/* Der Entwurf trennt Abschnitte ueber den Hintergrund, nicht ueber Linien.
   Die Trennlinien aus `.section` bleiben fuer die Inhaltsseiten stehen. */
.sec, .sec--text, .sec--alt, .sec--intro { border-top: 0; }

/* --- Typografie der Marketingseiten --------------------------------------- */
.t-hero  { font-size: clamp(2.1rem, 1.4rem + 3.4vw, 3.375rem); letter-spacing: -.03em; line-height: 1.06; }
.t-page  { font-size: clamp(1.9rem, 1.3rem + 2.8vw, 2.875rem); letter-spacing: -.028em; line-height: 1.1; }
.t-sec   { font-size: clamp(1.6rem, 1.2rem + 1.9vw, 2.3125rem); letter-spacing: -.025em; line-height: 1.16; }
.t-minor { font-size: clamp(1.3rem, 1.1rem + .9vw, 1.625rem); letter-spacing: -.022em; line-height: 1.22; }
.t-body  { font-size: var(--step-0); line-height: 1.62; color: var(--text-secondary); }
@media (min-width: 60rem) { .t-body { font-size: var(--step-1); } }

/* --- Zweispaltig, und einspaltig, wo es eng wird -------------------------- */
.duo { display: grid; gap: var(--gap-5); align-items: start; }
@media (min-width: 62rem) { .duo { grid-template-columns: 1fr 1fr; gap: 4rem; } }

/* --- Hero ----------------------------------------------------------------- */
.hero-cta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-3); }
.hero-count { font-family: var(--font-mono); font-size: var(--step-m); color: var(--text-tertiary); }

/* --- Die Aufnahmen auf der Landing Page (Entscheidung 274) ---------------
   Freigestellte Telefone in doppelter Aufloesung: 600 px Datei, 300 px
   Anzeige. Kein Schatten und keine Rundung — die Ecken sind durchsichtig,
   ein Schatten zeichnete das Rechteck dahinter nach. */
.figure--phone { max-width: 300px; }
.figure--phone img { display: block; box-shadow: none; border-radius: 0; }

/* **Die Telefone treten aus der Linie** (274). Die Aufnahmen enden unten mit
   einer geraden Schnittkante; der Abschnitt hat unten keinen Abstand, und
   die Kante liegt genau auf der Trennlinie zum naechsten. `display: block`
   am Bild, sonst laesst die Grundlinie ein paar Pixel Luft darunter. */
.landing > section + section { border-top: 1px solid var(--rule); }
/* **Abwechselnd hell und dunkel** (274), nach Position statt nach Klasse:
   der Abschnitt „Vorher ansehen" erscheint nur mit Beispieldaten, und ein
   fest vergebener Hintergrund stuende dann zweimal hintereinander. Nimmt
   „zwei Hintergruende, nicht acht" aus 237 fuer die Landing Page zurueck.
   `--band` ist dunkel die hellere Flaeche, hell die dunklere — `--surface`
   ist hell reines Weiss und vom Blatt (#F7F6F3) kaum zu unterscheiden. */
.landing > section:nth-of-type(odd)  { background: var(--ground); }
.landing > section:nth-of-type(even) { background: var(--band); }
.sec--stage { padding-bottom: 0; }
.duo--stage { align-items: center; }
.duo--stage > .figure--phone { align-self: end; justify-self: center; margin: 0; }
/* Zwei Spalten: das zweite Element nach links (Bild, oder die grosse Null).
   Einspaltig bleibt es unten, wo beim Telefon die Linie ist — deshalb steht
   es im Markup hinter dem Text. */
.duo--middle { align-items: center; }
/* Der Abstand, den der Abschnitt unten nicht mehr hat, traegt nebeneinander
   der Text — sonst stuende die letzte Zeile auf der Linie wie das Telefon.
   Einspaltig steht das Telefon darunter, und der Rasterabstand genuegt. */
@media (min-width: 62rem) {
  .duo--flip > :last-child { order: -1; }
  .duo--stage > .stack { padding-bottom: var(--sec-full); }
}
/* Die Jahreskarte ist nicht freigestellt, also traegt sie die Rundung selbst. */
.figure--card { max-width: 302px; margin: 0; justify-self: center; }
.figure--card img { border-radius: 14px; }

/* --- Das Regal aus vier Jahrzehnten (A4.3) -------------------------------- */
/* `minmax(0, 1fr)` und nicht `1fr` (274): eine `1fr`-Spalte ist mindestens so
   breit wie ihr laengstes Wort, und „PlayStation 2" machte die zweite Spalte
   bei 375 px 6 px breiter — mit ihr das Cover, das dann hoeher stand als die
   drei daneben. */
.decades { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gap-2); }
.decades figure { margin: 0; }
.decades img {
  display: block; width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: 6px; border: 1px solid var(--hairline); background: var(--surface);
}
.decades figcaption {
  margin-top: .5rem; font-family: var(--font-mono); font-size: 11px; overflow-wrap: anywhere;
  color: var(--text-tertiary); letter-spacing: .02em;
}
.decades figcaption b { display: block; color: var(--text-secondary); font-weight: 400; }

/* --- Die grosse Null (A4.4) ----------------------------------------------
   `slashed-zero`, weil eine 150px grosse 0 ohne Strich von einem O nicht zu
   unterscheiden ist — und die Zahl ist der ganze Abschnitt. */
.bigzero { display: flex; align-items: baseline; gap: var(--gap-3); }
.bigzero b {
  font-family: var(--font-mono); font-weight: 200;
  font-size: clamp(5rem, 14vw, 9.375rem); line-height: .82;
  font-variant-numeric: tabular-nums slashed-zero; color: var(--text);
  letter-spacing: -.04em;
}
.bigzero em { font-style: normal; font-size: var(--step-0); color: var(--text-tertiary); }

/* --- Listenvorschau (A4.6) ------------------------------------------------ */
.previews { display: grid; gap: var(--gap-3); }
@media (min-width: 48rem) { .previews { grid-template-columns: 1fr 1fr; } }
.listcard {
  display: block; text-decoration: none;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: 18px;
}
.listcard:hover { border-color: var(--accent-line); }
.listcard-covers { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
.listcard-covers img, .listcard-covers span {
  display: block; width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: 4px; background: var(--ground); border: 1px solid var(--hairline);
}
.listcard-title { margin-top: 12px; color: var(--text); font-weight: 500; }
.listcard-count { font-family: var(--font-mono); font-size: 12px; color: var(--text-tertiary); }

/* --- Fragen (A4.8) -------------------------------------------------------- */
.faq { display: grid; gap: var(--gap-4); }
@media (min-width: 55rem) { .faq { grid-template-columns: 1fr 1fr; column-gap: 3rem; } }
.faq h3 { font-size: 1.0625rem; font-weight: 600; letter-spacing: -.022em; color: var(--text); margin: 0; }
.faq p  { margin-top: .4rem; font-size: .96875rem; line-height: 1.6; color: var(--text-secondary); }

/* --- Anmeldekarte (A4.10) ------------------------------------------------- */
/* **Im dunkleren Ton** (274). Die Karte steht auf einem `--band`-Abschnitt,
   und `--surface` ist dunkel dieselbe Farbe — sie war nur noch am Rand zu
   erkennen. Das Feld darin tauscht dafuer die Rolle und nimmt `--band`,
   sonst verschwaende es in der Karte. */
.signup-card {
  max-width: 38rem; padding: 34px;
  background: var(--ground); border: 1px solid var(--hairline); border-radius: var(--radius);
}
.signup-card .field input { background: var(--band); }
/* `.signup` bringt selbst Flaeche, Rand und Polsterung mit (fuer den
   App-Streifen, wo es allein steht). In der Karte ergab das einen Kasten im
   Kasten — gleichfarbig bis 274, deshalb fiel nur der doppelte Rand auf. */
.signup-card .signup { background: none; border: 0; padding: 0; max-width: none; }

/* --- Presse (Entscheidung 276) -------------------------------------------
   Fuenfzehn nummerierte Abschnitte in einer Spalte von 55rem, getrennt durch
   Haarlinien, jeder mit einem eigenen „Copy"-Knopf. Nach Christians Entwurf,
   aber in den Token der Seite: hell und dunkel, Systemschriften, keine
   Farbe, die nicht schon hier steht. */
.press { max-width: calc(55rem + 2 * var(--pad-x)); padding-block: var(--sec-intro) var(--sec-full); }
.press-stand { margin: 0 0 var(--gap-4); }
.press-sec { display: flex; flex-direction: column; align-items: flex-start; gap: var(--gap-3);
  padding-block: var(--sec-text); border-top: 1px solid var(--rule); }
.press-sec--hero { border-top: 0; padding-top: 0; }
.press-sec--last { padding-bottom: 0; }
.press-sec > .label { margin: 0; }
.press-h1 { margin: 0; font-size: clamp(2.1rem, 1.3rem + 3.4vw, 3.375rem); line-height: 1.08;
  letter-spacing: -.03em; font-weight: 600; color: var(--text); text-wrap: pretty; }
.press-lead { margin: 0; font-size: var(--step-1); color: var(--text-secondary); }
.press-h2 { margin: 0; font-size: clamp(1.5rem, 1.2rem + 1.2vw, 1.875rem); line-height: 1.2;
  letter-spacing: -.02em; font-weight: 600; color: var(--text); }
.press-body { display: flex; flex-direction: column; gap: var(--gap-2); max-width: 42.5rem; width: 100%; }
.press-body p { margin: 0; line-height: 1.6; color: var(--text-secondary); text-wrap: pretty; }
.press-body .press-name { font-size: 1.25rem; font-weight: 600; color: var(--text); }
.press-body .press-quiet { color: var(--text-tertiary); }
.press-body .press-statement { font-size: 1.375rem; line-height: 1.4; color: var(--text); }

/* Kacheln unter dem Hero, Funktionsfelder und Dateien: ein Raster mit 1px
   Fugen aus dem Hintergrund (`gap: 1px` auf `--hairline`).

   **Nicht als Schatten der Zelle** — so stand es kurz (276), und die Linien
   waren weg: jede spaetere Zelle malt ihren Hintergrund ueber den Schatten
   der vorigen. Die Fugen aus dem Hintergrund brauchen dafuer volle Reihen,
   sonst steht der Rest als grauer Block da; die Spaltenbreiten unten sind so
   gewaehlt, dass sie aufgehen: sechs Felder in drei, zwei oder einer
   Spalte, vier Dateien in zwei oder einer. */
.press-tiles, .press-cells {
  display: grid; gap: 1px; width: 100%; margin: 0;
  background: var(--seam); border: 1px solid var(--seam);
  border-radius: 14px; overflow: hidden;
}
.press-tiles { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.press-cells { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
.press-tiles > div, .press-cells > div { background: var(--surface); padding: 18px 20px; min-width: 0; }
.press-tiles dt { font-family: var(--font-mono); font-size: 10px; letter-spacing: .11em;
  text-transform: uppercase; color: var(--text-tertiary); }
.press-tiles dd { margin: 7px 0 0; font-weight: 500; color: var(--text); }
.press-cells h3 { margin: 0; font-size: 1rem; font-weight: 600; color: var(--text); }
.press-cells p { margin: 10px 0 0; font-size: .90625rem; line-height: 1.55; color: var(--text-secondary); }

.press-jump { display: flex; flex-wrap: wrap; gap: 8px; }
.press-jump a, .press-tags li {
  display: inline-flex; align-items: center; min-height: 44px; padding-inline: 14px;
  font-family: var(--font-mono); font-size: 12.5px; text-decoration: none;
  border: 1px solid var(--hairline); border-radius: 999px; background: var(--surface);
}
.press-jump a { color: var(--link); }
.press-tags { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; }
.press-tags li { min-height: 36px; border-radius: 8px; color: var(--text-secondary); font-size: 13px; }

/* Zeilenlisten: eine Haarlinie zwischen den Punkten, nummeriert in Mono. */
.press-rows { list-style: none; margin: 0; padding: 0; }
.press-rows li { padding-block: 12px; border-top: 1px solid var(--row-rule); color: var(--text-secondary); }
.press-rows li:first-child { border-top: 0; }
.press-rows--numbered { counter-reset: schritt; }
.press-rows--numbered li { counter-increment: schritt; display: flex; gap: 14px; align-items: baseline; }
.press-rows--numbered li::before { content: counter(schritt, decimal-leading-zero);
  flex: none; width: 24px; font-family: var(--font-mono); font-size: 12px; color: var(--text-tertiary); }
.press-num { font-family: var(--font-mono); font-weight: 500; color: var(--text); }

.press-callout { align-self: flex-start; font-family: var(--font-mono); color: var(--text) !important;
  padding: 14px 18px; border-radius: 12px; background: var(--accent-wash); border: 1px solid var(--accent-line); }
.press-bignum { display: flex; align-items: baseline; gap: 10px; margin-block: 10px 6px; }
.press-bignum b { font-family: var(--font-mono); font-weight: 400; font-size: clamp(2.5rem, 6vw, 3.75rem);
  line-height: 1; letter-spacing: -.04em; color: var(--text); font-variant-numeric: tabular-nums; }
.press-bignum span { font-family: var(--font-mono); font-size: 13px; color: var(--text-tertiary); }

/* Dateien: jede Karte mit ihrer gemessenen Groesse (`_pressedateien`). */
.press-head-row { display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: var(--gap-3); width: 100%; }
.press-all { gap: 10px; }
.press-size { font-family: var(--font-mono); font-size: 11px; opacity: .8; }
.press-cells--assets { grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); }
.press-cells--assets > div { display: flex; flex-direction: column; }
.press-cells--assets p { flex: 1; color: var(--text-tertiary); }
.press-dl { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; margin-top: 6px;
  font-family: var(--font-mono); font-size: 12px; color: var(--link); text-decoration: none; }
.press-dl span { color: var(--text-tertiary); }

.press-facts { margin: 0; }
.press-facts > div { display: flex; flex-wrap: wrap; gap: 4px 20px; padding-block: 13px;
  border-top: 1px solid var(--row-rule); }
.press-facts > div:first-child { border-top: 0; }
.press-facts dt { flex: none; width: 11.875rem; font-family: var(--font-mono); font-size: 13px;
  color: var(--text-tertiary); }
.press-facts dd { margin: 0; font-weight: 500; color: var(--text); }

.press-card { display: flex; flex-direction: column; align-items: flex-start; gap: var(--gap-3);
  max-width: 47.5rem; padding: 28px; background: var(--surface);
  border: 1px solid var(--hairline); border-radius: 16px; }
.press-card p { margin: 0; line-height: 1.65; color: var(--text); text-wrap: pretty; }

.press-faq { gap: 0; max-width: 45rem; }
.press-faq > div { padding-block: 18px; border-top: 1px solid var(--row-rule); }
.press-faq > div:first-child { border-top: 0; padding-top: 0; }
.press-faq h3 { margin: 0 0 7px; font-size: 1rem; font-weight: 600; color: var(--text); }

/* Der Knopf: umrandet im Akzent, beim Boilerplate gefuellt. 44px hoch. */
.copy-btn {
  min-height: 44px; padding: 0 16px; cursor: pointer;
  font: 600 13px/1 var(--font-sans); color: var(--link);
  background: none; border: 1px solid var(--accent-line); border-radius: 999px;
}
.copy-btn:hover { border-color: var(--link); }
.copy-btn--fill { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.copy-btn--fill:hover { background: var(--accent-hover); color: var(--on-accent); }

/* --- Der lila Aufruf am Fuss von Presse und Changelog --------------------- */
.cta-band {
  background: var(--accent-wash); border-block: 1px solid var(--accent-line);
  padding-block: var(--sec-text);
}
.cta-band .btn { margin-top: var(--gap-3); }

/* --- Changelog ------------------------------------------------------------ */
.releases { max-width: 820px; }
.release { border-top: 1px solid var(--hairline); padding-top: var(--gap-3); }
.release + .release { margin-top: 34px; }
.release-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--gap-2); }
.release-version { font-family: var(--font-mono); font-size: 1.625rem; letter-spacing: -.02em; color: var(--text); }
.release-meta { font-family: var(--font-mono); font-size: 14px; color: var(--text-tertiary); }
.tagpill {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  border-radius: 999px; padding: 4px 9px;
  background: var(--accent-wash); border: 1px solid var(--accent-line); color: var(--link);
}
.tagpill--plain { background: none; border-color: var(--hairline); color: var(--text-tertiary); }
.release-part { display: grid; gap: var(--gap-2); margin-top: var(--gap-3); }
@media (min-width: 40rem) { .release-part { grid-template-columns: 110px 1fr; gap: var(--gap-3); } }
.release-part dt {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-tertiary); padding-top: .25rem;
}
.release-part dd { margin: 0; font-size: 1rem; line-height: 1.6; color: var(--text-secondary); }
.release-part dd + dd { margin-top: .35rem; }

/* **Ein Link mitten im Satz** (A0.5, zweiter Fall). Die Kontaktadresse steht
   auf drei Seiten im Fliesstext; ihr 44 Pixel Hoehe als *Layout* zu geben,
   wuerde den Absatz auseinanderreissen. `padding-block` auf einem
   `inline`-Element waechst nur die **Trefferflaeche** und laesst die
   Zeilenhoehe unberuehrt — genau der Fall, fuer den es das gibt.

   **Auf `mailto:` begrenzt und nicht auf alle Links.** Fuenf gepolsterte
   Links in einem Absatz haetten ueberlappende Flaechen, und dann trifft man
   den falschen. Eine Mailadresse steht in diesem Produkt nie in einer
   Aufzaehlung — sie steht allein am Ende eines Satzes.

   **Seit 274 an `.mail` statt an `a[href^="mailto:"]`**: kein Link fuehrt
   mehr direkt auf `mailto:`, sie gehen ueber `/contact`. Und die alte Regel
   traf auch „Contact" in der Fusszeile, das dadurch 28px hoeher war als
   seine Nachbarn und tiefer stand. */
.mail { padding-block: 14px; }
/* Die Adresse aus zwei Attributen — im HTML steht kein `x@y.z` (274). */
.addr::before { content: attr(data-u); }
.addr::after  { content: "@" attr(data-d); }

