/* ==========================================================================
   Sparks — Theme-eigenes Blatt
   Die Rolle von app/site.css auf der Website: Layout und Seitenteile, die es
   nur hier gibt.
   ==========================================================================

   ⚠️ Diese Datei definiert **keinen Token und keine Komponente neu**. Tokens,
   Grundstile und Komponenten kommen aus public/styleguide/css/ und werden beim
   Docker-Bau daneben gelegt (tokens.css, base.css, components.css). Wer hier
   eine Farbe schreibt statt `var(--color-…)`, hat eine zweite Quelle
   aufgemacht — genau das, was das Design-System ausschliesst (readme.md,
   research.md R6).

   Was hier steht, zerfällt in zwei Teile: oben die Stücke, die wörtlich aus
   app/site.css kommen (Schale, Kopfzeile, die beiden Umschalter, Fusszeile) —
   sie machen die Design-Parität aus und sind bei einer Änderung dort
   nachzuziehen; unten die Teile, die es nur auf Sparks gibt (Beitragsliste,
   Beitragsseite, Hinweise, Fehlerseite).
   ========================================================================== */

/* --------------------------------------------------------------------------
   Schale — wörtlich aus app/site.css
   -------------------------------------------------------------------------- */

/* ⚠️ Der Beschnitt gehört an genau ein Element, und zwar an das
   bildschirmbreite: `.site-shell` ist auf --container-max begrenzt und kappte
   ab etwa 1220px Fensterbreite die Blobs mitten in der Form (Befund
   2026-08-19, readme.md Regel 7).

   `clip`, nicht `hidden`: hidden machte das Element zum Scrollcontainer, und
   die sticky Kopfzeile klebte dann an ihm statt am Sichtfenster. */
.site-clip {
  overflow-x: clip;
}

.site-shell {
  /* Der freie Rand neben dem Inhalt — so weit darf ein Blob höchstens aus
     seinem Abschnitt laufen, ohne den Bildschirmrand zu berühren. 100vw zählt
     eine klassische Scrollbar mit; die 20px Abzug fangen das dort ab, wo der
     Wert überhaupt greift. */
  --shell-pad: var(--space-5);
  --gutter: calc(var(--shell-pad) + max(0px, (100vw - var(--container-max) - 20px) / 2));

  max-width: var(--container-max);
  margin-inline: auto;
  padding: var(--space-4) var(--shell-pad) var(--space-5);
}

/* Die Kopfzeile schwebt beim Scrollen über dem Inhalt.
   ⚠️ Ohne das Einrast-Verhalten der Website: Das hängt dort an React und an
   einem Scroll-Listener, und eine Publikation ist es nicht wert, dafür ein
   zweites Skript in den Browser zu schicken (contracts/theme.md §2). */
.site-shell > .site-header {
  position: sticky;
  top: var(--space-3);
  z-index: 20;
}

.site-main {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  padding-block: var(--space-6) var(--space-9);
}

/* --------------------------------------------------------------------------
   Kopfzeile: die beiden Umschalter — wörtlich aus app/site.css
   -------------------------------------------------------------------------- */

/* Ein Navigationseintrag bricht nie mitten im Wort um, und die Marke schon gar
   nicht: Als schrumpfbares Flex-Kind gibt sie zuerst nach, und dann bricht das
   Lockup »DIGITLZ AI« auf zwei Zeilen. */
.site-nav a {
  white-space: nowrap;
}

.site-header > .brand {
  flex: none;
  white-space: nowrap;
}

/* Theme-Umschalter: Mond im Light (Klick → Dark), Sonne im Dark (→ Light).
   Die Icon-Wahl geschieht rein per CSS und folgt data-theme bzw. der
   OS-Einstellung — deshalb stehen beide Zeichen im Markup. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--color-ink-soft);
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease),
    background var(--duration-fast) var(--ease);
}

.theme-toggle:hover {
  color: var(--color-ink);
  background: var(--color-surface);
}

.theme-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-halo);
  animation: focus-pulse var(--duration-pulse) var(--ease) infinite;
}

.theme-toggle-sun {
  display: none;
}

[data-theme="dark"] .theme-toggle-sun {
  display: block;
}

[data-theme="dark"] .theme-toggle-moon {
  display: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle-sun {
    display: block;
  }

  :root:not([data-theme="light"]) .theme-toggle-moon {
    display: none;
  }
}

/* Sprachumschalter: ein Ziel, nicht zwei (Christian, 2026-08-12). Die aktive
   Hälfte trägt die Fläche, die inaktive nichts — er zeigt damit an, welche
   Sprache gerade gilt, und bleibt trotzdem eine einzige Klickfläche. */
.sprache-schalter {
  display: inline-flex;
  align-items: center;
  gap: 0;
  min-height: 44px;
  border-radius: 999px;
  text-decoration: none;
  color: inherit;
}

.sprache-teil {
  padding: 3px var(--space-2);
  border-radius: 999px;
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.4;
  opacity: 0.6;
  transition: opacity var(--duration-fast) var(--ease),
    background var(--duration-fast) var(--ease);
}

.sprache-schalter:hover .sprache-teil {
  opacity: 1;
}

.sprache-schalter:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-halo);
}

/* Die aktive Hälfte ist die Umkehrung der Kopfzeile — sie dreht mit dem Theme
   mit, ohne eine eigene Farbe zu kennen. */
.sprache-teil[data-aktiv] {
  background: var(--color-ink);
  color: var(--color-bg);
  opacity: 1;
}

/* --------------------------------------------------------------------------
   Fusszeile — wörtlich aus app/site.css
   -------------------------------------------------------------------------- */

.site-footer a {
  color: inherit;
}

/* `:not(.btn)` ist hier kein Zierrat: Ohne es liegt diese Regel
   spezifitätsgleich mit `.site-nav a:not(.btn)` aus dem Design-System und
   verliert über die Ladereihenfolge. Dann griffe dort `--color-ink-soft` — auf
   der dunklen Fusszeilenfläche 2.07:1, wo AA 4.5:1 verlangt. */
.site-footer .site-nav a:not(.btn) {
  color: inherit;
  opacity: 0.8;
}

.site-footer .site-nav a:not(.btn):hover {
  color: inherit;
  opacity: 1;
}

.site-footer-brand p {
  margin-top: var(--space-1);
}

.site-footer-end {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-2);
}

/* --------------------------------------------------------------------------
   Übersicht: Titel, Rubrik-Filter, Beitragsliste
   -------------------------------------------------------------------------- */

.section-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: 68ch;
}

/* Der Blitz sitzt im Titel und ist die Holo-Stelle dieses Sichtbereichs
   (readme.md Regel 9). `gap` statt eines Leerzeichens im Markup, damit der
   Abstand nicht an der Schriftgrösse hängt. */
.sparks-titel {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.sparks-untertitel {
  color: var(--color-ink-soft);
}

/* Die drei Rubriken als Pillen — die eine organische Form, die das
   Design-System erlaubt (readme.md Regel 6). Sie umbrechen statt zu
   schrumpfen: Ein abgeschnittener Rubrikname ist schlimmer als eine zweite
   Zeile. */
.rubrik-filter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.rubrik-filter a {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 var(--space-4);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-pill);
  color: var(--color-ink-soft);
  font-size: var(--text-small);
  font-weight: 500;
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease),
    background var(--duration-fast) var(--ease),
    border-color var(--duration-fast) var(--ease);
}

.rubrik-filter a:hover {
  color: var(--color-ink);
  border-color: var(--color-ink-soft);
}

/* Der Zustand steht im `aria-current`, nicht in einer Zustandsklasse: Ein
   Attribut, das ohnehin für Screenreader gesetzt werden muss, soll auch das
   Aussehen tragen — dann kann es nicht auseinanderlaufen. Die Umkehrung des
   Seitengrunds wie beim Sprachumschalter, also ohne eigene Farbe. */
.rubrik-filter a[aria-current="page"] {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-bg);
}

/* Eine Liste, keine Kacheln: Beiträge sind Text, und Text liest sich in einer
   Spalte. Die Breite begrenzt sich selbst — eine Zeile über 75 Zeichen
   verliert der Blick beim Zurückspringen. */
.sparks-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
}

.sparks-eintrag {
  max-width: 68ch;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Mit Titelbild wird der Eintrag zweispaltig: Bild links, Text rechts. Das
   Textmass bleibt, was es war — es wandert nur eine Ebene tiefer, damit der
   Eintrag als Ganzes um die Bildspalte breiter werden darf. Ein Beitrag ohne
   Titelbild behält die einspaltige Form; die Liste mischt beide, ohne dass
   eine leere Spalte stehen bleibt. */
.sparks-eintrag--mit-bild {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: var(--space-5);
  align-items: start;
  max-width: calc(68ch + 260px + var(--space-5));
}

.sparks-eintrag-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

/* `aspect-ratio` hält den Platz frei, bevor die Datei da ist — sonst rutscht
   die Liste beim Laden nach unten. 16/9 wie das Titelbild der Beitragsseite:
   ein Bild, zwei Orte, ein Zuschnitt. */
.sparks-eintrag-bild {
  display: block;
  overflow: hidden;
  border-radius: var(--radius-m);
}

.sparks-eintrag-bild img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* Rubrik und Meta-Zeile tragen dieselbe leise Auszeichnung wie die Captions
   der Website: klein, versal, gesperrt. Sie ordnen ein, sie lesen sich nicht. */
.sparks-rubrik,
.sparks-meta,
.beitrag-rubrik,
.beitrag-meta {
  font-size: var(--text-caption);
  color: var(--color-ink-soft);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Die Meta-Zeile ist eine Aufzählung ohne Aufzählungszeichen — der Abstand
   trennt, kein Trennzeichen im Markup, das ein Screenreader mitläse. */
.sparks-meta,
.beitrag-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
}

.sparks-eintrag-titel {
  font-size: var(--text-h3);
  line-height: 1.25;
}

.sparks-eintrag-titel a {
  color: inherit;
  text-decoration: none;
}

.sparks-eintrag-titel a:hover {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.sparks-teaser {
  color: var(--color-ink-soft);
}

/* Ghosts {{pagination}} bringt ihr eigenes Markup mit: nav.pagination mit
   .older-posts, .newer-posts und .page-number. */
.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-8);
  font-size: var(--text-small);
}

.pagination .page-number {
  color: var(--color-ink-soft);
}

/* --------------------------------------------------------------------------
   Beitragsseite
   -------------------------------------------------------------------------- */

.beitrag {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.beitrag-kopf {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: 68ch;
}

/* Der Weg zurück in die Rubrik — Pfeil und Wort als ein Ziel (Christian,
   2026-09-15: die blosse Beschriftung sah nicht nach einem Weg aus). */
.beitrag-rubrik a {
  color: inherit;
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2);
  text-decoration: none;
  border-bottom: 1px solid var(--color-line);
}

.beitrag-rubrik a:hover {
  border-bottom-color: currentColor;
}

/* Der Pfeil rückt beim Überfahren ein Stück in seine Richtung — dieselbe
   Geste wie die `→` der Website, nur andersherum. `inline-block`, weil ein
   `transform` an einem reinen Inline-Element nicht greift. */
.beitrag-rubrik-pfeil {
  display: inline-block;
  transition: transform var(--duration-fast) var(--ease);
}

.beitrag-rubrik a:hover .beitrag-rubrik-pfeil {
  transform: translateX(-3px);
}

@media (prefers-reduced-motion: reduce) {
  .beitrag-rubrik-pfeil {
    transition: none;
  }

  .beitrag-rubrik a:hover .beitrag-rubrik-pfeil {
    transform: none;
  }
}

/* Schlagworte sind unverlinkt: Es gibt keine Tag-Seiten (`taxonomies: {}`),
   ein Link führte ins 404. Sie ordnen ein, sie führen nicht weiter. */
.beitrag-schlagworte {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  max-width: 68ch;
}

.beitrag-schlagworte li {
  padding: 2px var(--space-3);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-pill);
  font-size: var(--text-caption);
  color: var(--color-ink-soft);
  letter-spacing: 0.04em;
}

.beitrag-sprachpaar {
  max-width: 68ch;
  font-size: var(--text-small);
}

/* Das Titelbild ist die eine Fläche, die ihre eigenen Farben trägt (readme.md
   Regel 8 sinngemäss). `aspect-ratio` hält den Platz frei, bevor die Datei da
   ist — sonst springt der Text beim Laden nach unten. */
.beitrag-bild {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--radius-m);
}

/* Die Textspalte. Alles, was Ghosts Editor erzeugt, landet hier.
   
   ⚠️ Die Breite begrenzt **die Kinder**, nicht den Container — und das ist der
   Grund: Ghosts Editor kennt für Bilder und Karten drei Breiten, und die
   beiden weiten (`.kg-width-wide`, `.kg-width-full`) müssen aus der Textspalte
   ausbrechen dürfen. Läge die Grenze am Container, könnten sie das nicht, und
   gscan lehnt ein Theme ohne diese beiden Klassen ab. */
.beitrag-inhalt {
  display: flex;
  flex-direction: column;
  /* ⚠️ `flex-start`, nicht `center`: Der Beitragskopf darüber steht links an
     der Shell-Kante. Zentriert lag die Textspalte darunter um die halbe
     Restbreite eingerückt — Titel links, Text in der Mitte, und zwischen
     beiden eine Stufe, die niemand gemeint hat (gesehen am Abbild
     2026-09-15). Eine Kante für alles. */
  align-items: flex-start;
  gap: var(--space-4);

  /* Das Textmass der Spalte — **in rem, nicht in ch**.

     ⚠️ `ch` misst die Breite der Null in der Schrift **des Elements, an dem es
     steht**. Mit `max-width: 68ch` an jedem Kind bekam eine H2 in der
     Display-Schrift bei 2 rem ein Vielfaches der Absatzbreite: Die
     Überschriften standen links aussen über die ganze Shell, der Fliesstext
     schmal in der Mitte, und das Zitat wieder anders (gesehen am Abbild
     2026-09-15). Der Fehler ist deshalb so hartnäckig, weil jede einzelne
     Regel für sich richtig aussieht.

     42 rem entsprechen rund 68 Zeichen im Fliesstext — dieselbe Absicht,
     nur unabhängig von der Schrift des jeweiligen Kindes. */
  --textmass: 42rem;
}

.beitrag-inhalt > * {
  width: 100%;
  max-width: var(--textmass);
}

/* Breit: eine Stufe über der Textspalte, aber nie über die Shell hinaus. */
.beitrag-inhalt > .kg-width-wide {
  max-width: min(100%, calc(var(--textmass) * 1.35));
}

/* Voll: die ganze Breite der Shell. Weiter geht es nicht — den Rand darüber
   hinaus trägt `.site-clip`, und der gehört den Blobs (Regel 7). */
.beitrag-inhalt > .kg-width-full {
  max-width: none;
}

.beitrag-inhalt img,
.beitrag-inhalt figure {
  max-width: 100%;
  height: auto;
}

/* ⚠️ Browser geben `<figure>` von Haus aus `margin: 1em 40px`. Ghosts
   Bildkarten sind Figures — ohne diese Zeile stünde jedes Bild im Beitrag
   40 px eingerückt und liefe damit aus der Kante, an der Titel, Text und
   Überschriften stehen. Der Abstand nach oben und unten kommt vom `gap` der
   Spalte, nicht von der Figure. */
.beitrag-inhalt figure {
  margin: 0;
}

/* `block`, sonst setzt die Zeilenschachtel unter jedes Bild ein paar Pixel
   Luft, die niemand bestellt hat. Der Radius ist derselbe wie beim Titelbild
   — ein Bild im Beitrag ist dieselbe Sorte Fläche. */
.beitrag-inhalt img {
  display: block;
  border-radius: var(--radius-m);
}

/* Bildunterschriften der Karten — Ghost setzt sie als <figcaption>.
   Linksbündig wie alles andere auf der Seite: Seit die Textspalte an der
   Kante des Beitragskopfs steht, wäre eine zentrierte Zeile die einzige,
   die ausschert. */
.beitrag-inhalt figcaption {
  margin-top: var(--space-2);
  font-size: var(--text-caption);
  color: var(--color-ink-soft);
  text-align: left;
}

.beitrag-zurueck {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  font-size: var(--text-small);
}

/* --------------------------------------------------------------------------
   Karten aus Ghosts Editor
   --------------------------------------------------------------------------

   Ghost liefert für seine Karten ein eigenes Stylesheet (`cards.min.css`,
   eingebunden über {{ghost_head}}) und package.json sagt, welche davon —
   sieben, die Sparks wirklich braucht. Was hier steht, zieht ihre Typografie
   auf die Tokens des Hauses: Ghosts Fassung bringt eigene Grauwerte und eigene
   Radien mit, und die stünden neben allem anderen auf der Seite falsch.

   ⚠️ Keine Farbwerte, nur Tokens — damit die Karten Hell und Dunkel von selbst
   mitmachen. Ghosts eigene Werte tun das nicht. */

/* Zitat — dieselbe Bauform wie `.quote` des Design-Systems: eine Fläche, kein
   Anführungszeichen als Grafik, Archivo für den Satz. */
.beitrag-inhalt blockquote {
  margin: 0;
  padding: var(--space-5) var(--space-6);
  background: var(--color-surface);
  border-radius: var(--radius-m);
  font-family: var(--font-display);
  font-size: var(--text-h4);
  font-weight: 700;
  line-height: 1.35;
}

.beitrag-inhalt blockquote cite,
.beitrag-inhalt blockquote footer {
  display: block;
  margin-top: var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: 400;
  font-style: normal;
  color: var(--color-ink-soft);
}

/* Code — monochrom, ohne Syntaxfarben. Regel 1 lässt keine Buntfarbe zu, und
   eine halbe Einfärbung wäre schlimmer als gar keine. */
.beitrag-inhalt pre {
  margin: 0;
  padding: var(--space-4);
  overflow-x: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-m);
  font-size: var(--text-small);
  line-height: 1.55;
}

.beitrag-inhalt :not(pre) > code {
  padding: 2px 5px;
  background: var(--color-surface);
  border-radius: var(--radius-s);
  font-size: 0.9em;
}

/* Hinweiskarte (callout) — Ghost setzt den Emoji als eigenes Element daneben. */
.beitrag-inhalt .kg-callout-card {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--color-surface);
  border-left: 3px solid var(--color-ink-soft);
  border-radius: var(--radius-s);
}

/* Aufklappen (toggle) — natives <details> wäre schöner, Ghost baut es aus
   Divs; die Klassen sind die einzige Handhabe. */
.beitrag-inhalt .kg-toggle-card {
  padding: var(--space-4);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-m);
}

.beitrag-inhalt .kg-toggle-heading-text {
  font-family: var(--font-display);
  font-weight: 700;
}

/* Lesezeichen (bookmark) — eine Karte mit Titel, Beschreibung und Herkunft. */
.beitrag-inhalt .kg-bookmark-card a {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-m);
  color: inherit;
  text-decoration: none;
}

.beitrag-inhalt .kg-bookmark-title {
  font-weight: 700;
}

.beitrag-inhalt .kg-bookmark-description,
.beitrag-inhalt .kg-bookmark-metadata {
  font-size: var(--text-small);
  color: var(--color-ink-soft);
}

/* Knopf (button) — die Pille des Design-Systems, ohne Holo: Der Blitz ist die
   eine Holo-Stelle auf Sparks (Regel 9). */
.beitrag-inhalt .kg-btn {
  display: inline-flex;
  align-items: center;
  min-height: 42px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-pill);
  background: var(--color-ink);
  color: var(--color-bg);
  font-size: var(--text-small);
  font-weight: 700;
  text-decoration: none;
}

/* Galerie — Ghosts eigenes Raster, nur die Lücke auf unsere Skala gezogen. */
.beitrag-inhalt .kg-gallery-row {
  display: flex;
  gap: var(--space-2);
}

.beitrag-inhalt .kg-gallery-image img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-s);
}

/* --------------------------------------------------------------------------
   Hinweise und Formular-Rückmeldung
   -------------------------------------------------------------------------- */

/* Ein Hinweis ist standardmässig **nicht da**, nicht bloss unsichtbar: Der
   Sprachumschalter eines Beitrags ohne Gegenfassung zeigt auf `/en/#nur-deutsch`,
   und erst der Ankersprung macht den Satz sichtbar. Das ist die ganze Mechanik,
   ohne eine Zeile JavaScript (contracts/adressen-und-routen.md §4).

   ⚠️ `display: none` und nicht `visibility`: Ein bloss unsichtbarer Hinweis
   bliebe für Screenreader da und läse sich wie eine Aussage über den Beitrag,
   den man gerade offen hat. */
.hinweis {
  display: none;
}

.hinweis:target,
.hinweis--sichtbar {
  display: block;
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--color-ink-soft);
  background: var(--color-surface);
  border-radius: var(--radius-s);
  font-size: var(--text-small);
}

/* --------------------------------------------------------------------------
   Eintragung (US4, T060)
   --------------------------------------------------------------------------

   Eine Karte am Fuss der Übersicht und am Fuss jedes Beitrags. Sie borgt sich
   Rahmen und Radius von `.card--outline` aus dem Design-System, ohne die
   Komponente neu zu definieren — deshalb stehen hier nur Abstände, Raster und
   die Zustände des Formulars.

   ⚠️ **Kein Holo, kein Blob.** Auf der Übersicht ist der Blitz am Titel die
   Holo-Stelle des Sichtbereichs, auf der Beitragsseite der Fuss-Blob
   (readme.md Regel 4). Ein leuchtender Rahmen um das Formular wäre die zweite
   — und läge ausgerechnet dort, wo jemand etwas eingeben soll. */

.eintrag {
  margin-top: var(--space-7);
  padding: var(--space-5);
  border: 1.5px solid var(--color-ink);
  border-radius: var(--radius-m);
  background: var(--color-bg);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.eintrag-titel {
  font-family: var(--font-display);
  font-size: var(--text-h4);
  margin: 0;
}

.eintrag-text {
  margin: 0;
  max-width: 60ch;
  color: var(--color-ink-soft);
  font-size: var(--text-small);
}

/* Eingabe und Knopf nebeneinander, solange der Platz reicht. `align-items:
   flex-end` statt `center`: Über der Eingabe steht ein Label, über dem Knopf
   nicht — auf der Mitte ausgerichtet stünde der Knopf sichtbar zu hoch. */
.eintrag-formular {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
}

.eintrag-feld {
  flex: 1 1 22rem;
  /* `min-width: 0` zähmt das Flex-Kind: Ohne die Zeile wächst ein `input` über
     seine Spalte hinaus und schiebt den Knopf aus der Zeile, statt umzubrechen. */
  min-width: 0;
}

.eintrag-feld label {
  font-size: var(--text-small);
  color: var(--color-ink-soft);
}

.eintrag-knopf {
  /* Der Knopf bricht als Ganzes um, statt schmaler zu werden. */
  flex: 0 0 auto;
}

/* Während Portal die Mail verschickt, trägt das Formular `loading`. Der Knopf
   wird dann unklickbar — ohne das liesse sich die Eintragung mehrfach
   abschicken, und jeder Klick wäre eine weitere Mail. */
form[data-members-form].loading .eintrag-knopf {
  opacity: 0.6;
  pointer-events: none;
}

/* Die beiden Rückmeldungen und der technische Fehlertext liegen unter der
   Zeile, über die ganze Breite. */
.eintrag-rueckmeldung,
.eintrag-fehlertext {
  flex: 1 0 100%;
  margin: 0;
}

/* Portals eigener Fehlertext — knapp, leise und nur da, wenn er etwas sagt.
   Der erklärende Satz darüber steht fest im Template und trägt die Aussage;
   das hier ist die technische Beigabe (siehe partials/eintrag-de.hbs). */
.eintrag-fehlertext {
  font-size: 0.75rem;
  color: var(--color-ink-soft);
}

.eintrag-fehlertext:empty {
  display: none;
}

.eintrag-hinweis {
  margin: 0;
  font-size: 0.75rem;
  color: var(--color-ink-soft);
}

/* Ghosts Members-Formular blendet seine Rückmeldungen über Zustandsklassen am
   Formular ein. Beide Sätze stehen im Markup, sichtbar ist immer höchstens
   einer (US4, T059). */
.eintrag-rueckmeldung {
  display: none;
  font-size: var(--text-small);
}

form[data-members-form].success .eintrag-rueckmeldung--ok,
form[data-members-form].error .eintrag-rueckmeldung--fehler {
  display: block;
}

form[data-members-form].error .eintrag-rueckmeldung--fehler {
  color: var(--color-error);
}

/* --------------------------------------------------------------------------
   Fehlerseiten
   -------------------------------------------------------------------------- */

.fehler {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 68ch;
}

.fehler-wege {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
}

/* --------------------------------------------------------------------------
   Schmale Schirme
   --------------------------------------------------------------------------

   Die Kopfzeile trägt Marke, sechs Wege und zwei Umschalter. Sie bekommt
   keinen Menü-Knopf wie die Website — der bräuchte JavaScript. Stattdessen
   umbricht sie: erst die Navigation unter die Marke, dann die Einträge
   untereinander. Geprüft von 360 bis 1440px, ohne Seitwärtsscrollen (FR-016). */

@media (max-width: 860px) {
  .site-header {
    flex-wrap: wrap;
  }

  /* Die Navigation nimmt die volle Breite der zweiten Zeile; die beiden
     Umschalter bleiben in der ersten neben der Marke. */
  .site-header > .site-nav {
    order: 3;
    flex-basis: 100%;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
  }

  .site-shell {
    --shell-pad: var(--space-4);
  }
}

@media (max-width: 760px) {
  /* Unter dieser Breite bliebe neben 260 px Bild keine lesbare Textspalte —
     ab hier steht das Bild über dem Text und nimmt die volle Breite. */
  .sparks-eintrag--mit-bild {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-3);
  }
}

@media (max-width: 620px) {
  /* Unter dieser Breite blieben für die Eingabe neben dem Knopf keine zwanzig
     Zeichen — ab hier steht der Knopf unter dem Feld und nimmt die volle
     Breite, damit er mit dem Daumen zu treffen ist. */
  .eintrag {
    padding: var(--space-4);
  }

  .eintrag-feld {
    flex: 1 1 100%;
  }

  .eintrag-knopf {
    flex: 1 1 100%;
  }
}

@media (max-width: 520px) {
  .site-shell {
    --shell-pad: var(--space-3);
  }

  .site-shell > .site-header {
    /* Auf dem Telefon nimmt eine dreizeilige Kopfzeile den halben Schirm —
       hier gibt sie das Schweben auf und scrollt mit. */
    position: static;
  }

  .site-footer {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-5);
  }

  .site-footer-end {
    align-items: flex-start;
  }
}
