/* Farbtoken aus app.css uebernommen — nicht hier aendern. */
:root {
  --bg: #0d0d0f;
  --surface: #18181b;
  --surface-2: #202024;
  --surface-3: #26262b;
  --border: #2a2a2f;
  --border-soft: #232327;
  --text: #ece9e4;
  --text-dim: #8c8a86;
  --text-faint: #86847f;
  --text-ghost: #5a5955;
  --accent: #e8590c;
  --accent-soft: #f2864d;
  --accent-bg: rgba(232, 89, 12, 0.1);
  --accent-line: rgba(232, 89, 12, 0.28);
  --success: #5fd88f;
  --success-bg: rgba(95, 216, 143, 0.1);
  --warn: #f2b84d;
  --warn-bg: rgba(242, 184, 77, 0.12);
  --danger: #f16060;
  --danger-bg: rgba(241, 96, 96, 0.12);

  --radius: 10px;
  --radius-sm: 8px;
  --radius-lg: 14px;
  --sidebar-w: 236px;
  --topbar-h: 60px;
  --mono: 'IBM Plex Mono', ui-monospace, monospace;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.22);
}

/* ==========================================================================
   Das Magazin.

   Die Farbtoken stehen NICHT hier. bauen.mjs zieht den :root-Block aus
   app.css und setzt ihn beim Bau oben an diese Datei. Sonst gaebe es zwei
   Wahrheiten fuer dieselben Farben, und die eine liefe der anderen davon.

   Die App ist rein dunkel -- kein Themenschalter, keine Medienabfrage.
   Deshalb hat auch das Magazin nur einen Zustand; das ist eine
   Entscheidung der bestehenden Seite, nicht meine.

   app.css wird auf den Magazinseiten bewusst NICHT geladen: dort stehen
   Seitenleiste, Kopfleiste und Anmeldung der Anwendung. Ein Beitrag
   braucht nichts davon, und die Regeln wuerden sich in die Quere kommen.
   ========================================================================== */

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

body.magazin {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font:
    400 16px/1.72 "Inter",
    system-ui,
    -apple-system,
    "Segoe UI",
    sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* --- Kopf und Fuss -------------------------------------------------------- */

/* Die Kopfzeile klebt oben.

   Auf der Startseite scrollt man an 4.000 Pixeln vorbei; ohne das ist
   der Anmelde-Knopf nach dem ersten Bildschirm weg. Das Band traegt den
   Hintergrund und liegt ueber allem, der Kasten darin haelt die Breite.

   backdrop-filter statt voller Deckkraft: darunter durchscheinende
   Inhalte verraten, dass die Seite weiterlaeuft. Wo der Filter fehlt,
   greift die Farbe darunter -- deshalb steht sie ausdruecklich da und
   nicht nur als Ersatz. */
.mag-kopf-band {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--band);
  border-bottom: 1px solid var(--border-soft);
  backdrop-filter: saturate(1.3) blur(10px);
  -webkit-backdrop-filter: saturate(1.3) blur(10px);
}

/* Breiter als der Inhalt (900px): das Menue traegt jetzt neun Punkte mit
   den vollen Namen aus der alten Seite, und "Softwareentwicklung" allein
   ist neunzehn Zeichen. In 900 Pixeln braeuchte es zwei Zeilen, wo eine
   reicht. Der Text darunter bleibt bei 900. */
.mag-kopf {
  display: flex;
  align-items: center;
  gap: 24px;
  max-width: 1180px;
  margin: 0 auto;
  padding: 16px 24px;
}

.mag-logo {
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.02em;
  color: var(--text);
  text-decoration: none;
}

/* Aus zwei Verweisen sind acht geworden. Sie brechen um, statt die
   Zeile zu sprengen -- kein Aufklappmenue, das waere Javascript fuer
   acht Woerter. */
.mag-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 4px;
  margin-left: auto;
  justify-content: flex-end;
}

.mag-nav a {
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  color: var(--text-dim);
  text-decoration: none;
}

.mag-nav a:hover {
  background: var(--surface-2);
  color: var(--text);
}

/* Wo man gerade ist. aria-current traegt die Auskunft fuer den
   Screenreader, der Strich darunter fuer alle anderen -- eine Farbe
   allein ist zu wenig, wer sie nicht unterscheiden kann, sieht keinen
   Unterschied. */
.mag-nav a[aria-current="page"] {
  color: var(--text);
  box-shadow: inset 0 -2px 0 var(--accent);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

/* Der Werkzeug-Knopf.

   Er ist der einzige Punkt im Menue, der nicht auf die Hauptseite
   fuehrt, sondern in die App -- deshalb sieht er anders aus: umrahmt im
   Akzent, mit einer Rakete davor. Gefuellt waere er zu laut fuer eine
   Menuezeile; der Rahmen reicht, um ihn herauszuheben. */
.mag-nav-app {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 6px;
  border: 1px solid var(--accent);
  color: var(--accent-soft) !important;
  font-weight: 600;
  transition:
    background-color 0.16s ease,
    color 0.16s ease;
}

.mag-nav-app:hover {
  background: var(--accent) !important;
  color: var(--auf-akzent) !important;
}

.rakete {
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
}

@media (max-width: 640px) {
  .mag-kopf {
    flex-wrap: wrap;
    gap: 12px;
  }

  .mag-nav {
    margin-left: 0;
    justify-content: flex-start;
  }

  .mag-nav a {
    padding: 5px 9px;
    font-size: 0.82rem;
  }

  .mag-nav-app {
    margin-left: 0;
  }

  /* Auf dem Handy umbricht das Menue ohnehin auf drei Zeilen. Haengen
     die beiden Knoepfe hinten dran, bekommen sie eine vierte -- 34
     Pixel, die oben auf dem Schirm knapp sind. Also rueckt das Menue
     ganz nach unten und die Knoepfe stehen rechts neben dem Logo, wo
     auf der ersten Zeile ohnehin Platz frei ist. */
  .mag-nav {
    order: 3;
    width: 100%;
  }

  .kopf-knoepfe {
    margin-left: auto;
  }
}

.mag-huelle {
  max-width: 900px;
  margin: 0 auto;
  padding: 34px 24px 60px;
}

.mag-fuss {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  max-width: 900px;
  margin: 0 auto;
  padding: 22px 24px 40px;
  border-top: 1px solid var(--border-soft);
  font-size: 0.85rem;
  color: var(--text-ghost);
}

.mag-fuss a {
  color: var(--text-dim);
}

/* --- Beitrag -------------------------------------------------------------- */

.artikel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 0 0 34px;
  overflow: hidden;
}

.kopfbild {
  background: var(--surface-2);
  color: var(--accent);
  line-height: 0;
}

.kopfbild svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Der Kopf laeuft auf derselben Spur wie der Text darunter.

   Seit die Karte auf grossen Bildschirmen breiter ist als der Text,
   standen Rubrik, Ueberschrift und Datum am linken Kartenrand, waehrend
   der Fliesstext 236 Pixel weiter innen anfing. Zwei verschiedene
   Fluchten auf derselben Seite -- das sieht nicht nach Absicht aus,
   sondern nach Versehen. Dieselbe Breite und dieselbe Zentrierung wie
   die Absaetze, also stehen sie untereinander. */
/* DIE LUFT ZUM KARTENRAND STEHT AN EINER STELLE.

   Vorher stand 34px drei Mal einzeln da -- im Kopf, im Fliesstext, und
   als 68px (das Doppelte) in der Breitenrechnung darunter. Wer einen
   Wert aendert und die anderen uebersieht, bekommt einen Text, der nicht
   mehr unter seiner Ueberschrift steht.

   Sie waechst jetzt mit: eng auf dem Handy, wo jeder Pixel Textbreite
   zaehlt, grosszuegig auf dem Bildschirm, wo die Karte seit dem Ausbruch
   nach links und rechts ohnehin 240 Pixel breiter ist als der uebrige
   Inhalt. Am staerksten wirkt das in der Mitte -- auf einem Tablet
   stiess der Text vorher fast an die Kante, waehrend er auf dem Desktop
   von der 72ch-Grenze ohnehin mittig gehalten wird. */
.artikel {
  --luft: clamp(20px, 3.4vw, 56px);

  /* DIE KARTE IST SO BREIT WIE DER TEXT DARIN, plus die Luft an den
     Seiten. Damit stehen Kartenrand, Ueberschrift, Fliesstext,
     Newsletter und Autorenbox auf derselben Kante -- vorher waren es
     drei verschiedene Breiten: 1092 fuer die Karte, 733 fuer Kopf und
     Autor, 621 fuer den Text.

     72ch ist die Textbreite, nicht willkuerlich: darueber verliert das
     Auge beim Zeilenwechsel den Anschluss. Die Karte richtet sich nach
     dem Text, nicht umgekehrt. */
  max-width: calc(72ch + 2 * var(--luft));
  margin-left: auto;
  margin-right: auto;
}

/* Wer eine Tabelle hat, darf breiter werden -- der Text darin bleibt bei
   72 Zeichen und mittig, nur die Tabelle nutzt den Zugewinn. */
.artikel-breit {
  max-width: none;
}

.artikel-kopf,
.newsletter,
.autor {
  max-width: calc(72ch + 2 * var(--luft));
  margin-left: auto;
  margin-right: auto;
}

.artikel-kopf {
  padding: 26px var(--luft) 0;
}

.marke-klein {
  display: inline-block;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-bg);
  border: 1px solid var(--accent-line);
  border-radius: 999px;
  padding: 3px 11px;
  text-decoration: none;
}

.artikel-kopf h1 {
  margin: 14px 0 8px;
  font-size: clamp(1.6rem, 3.6vw, 2.15rem);
  line-height: 1.22;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.artikel-meta {
  margin: 0;
  font-size: 0.84rem;
  color: var(--text-faint);
}

/* --- Fliesstext ----------------------------------------------------------- */

/* DIE ZEILENBREITE HAENGT AM TEXT, NICHT AM BLOCK.

   Vorher stand die Begrenzung auf 68ch hier oben -- und damit galt sie
   auch fuer Tabellen, Codebloecke und Bilder. Das Ergebnis auf einem
   breiten Bildschirm: eine Vergleichstabelle mit 716 Pixeln Inhalt
   quetschte sich in einen 519 Pixel breiten Scrollkasten, waehrend
   rechts daneben 300 Pixel leer standen. Acht der 56 Beitraege haben
   solche Tabellen.

   Jetzt spannt sich .prosa ueber die volle Kartenbreite, und nur die
   Textelemente bekommen die Begrenzung. Fliesstext bleibt lesbar, alles
   Breite darf breit sein. */
.prosa {
  padding: 8px var(--luft) 0;
}

/* Der Text steht mittig in der Karte, nicht links angeschlagen.

   Vorher klebte er am linken Rand, und rechts blieb ein Drittel der
   Karte leer -- was aussieht, als haette jemand vergessen, etwas
   hinzustellen. Mit auto an beiden Seiten steht die Spalte in der Mitte,
   und die Karte wirkt gesetzt statt halb gefuellt.

   Tabellen, Bilder und Codebloecke sind hier bewusst NICHT aufgezaehlt.
   Sie behalten die volle Breite -- das war der Grund fuer die Umstellung
   ueberhaupt. */
.prosa p,
.prosa ul,
.prosa ol,
.prosa blockquote,
.prosa h2,
.prosa h3,
.prosa h4 {
  max-width: 72ch;
  margin-left: auto;
  margin-right: auto;
}

.prosa h2,
.prosa h3,
.prosa h4 {
  line-height: 1.3;
  letter-spacing: -0.015em;
  /* Die Kopfzeile klebt jetzt oben und ist rund 70 Pixel hoch. Ohne
     diesen Abstand landet ein Sprung auf einen Anker genau darunter,
     und die Ueberschrift, die man gesucht hat, ist verdeckt. */
  scroll-margin-top: 92px;
}

.prosa h2 {
  margin: 34px auto 12px;
  font-size: 1.34rem;
}
.prosa h3 {
  margin: 26px auto 10px;
  font-size: 1.1rem;
}
.prosa h4 {
  margin: 22px auto 8px;
  font-size: 1rem;
  color: var(--text-dim);
}

.prosa p {
  margin: 0 auto 17px;
}

.prosa a {
  color: var(--accent-soft);
  text-underline-offset: 2px;
}

.prosa ul,
.prosa ol {
  margin: 0 auto 17px;
  padding-left: 22px;
}

.prosa li {
  margin-bottom: 7px;
}

.prosa img {
  display: block;
  width: 100%;
  height: auto;
  margin: 22px 0;
  border-radius: var(--radius);
  border: 1px solid var(--border);
}

.prosa blockquote {
  margin: 22px auto;
  padding: 2px 0 2px 18px;
  border-left: 3px solid var(--accent-line);
  color: var(--text-dim);
}

.prosa code {
  font-family: var(--mono);
  font-size: 0.88em;
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1px 5px;
}

.prosa pre {
  margin: 20px 0;
  padding: 15px 17px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 0.86rem;
  line-height: 1.6;
}

.prosa pre code {
  background: none;
  border: 0;
  padding: 0;
  font-size: inherit;
}

/* Tabellen sind in diesen Beitraegen oft breiter als der Text. Sie
   scrollen in ihrem eigenen Kasten, damit die Seite es nicht tut. */
.tabelle-rahmen {
  margin: 22px 0;
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.prosa table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.9rem;
}

.prosa th,
.prosa td {
  padding: 10px 14px;
  text-align: left;
  border-bottom: 1px solid var(--border-soft);
  vertical-align: top;
}

.prosa th {
  background: var(--surface-2);
  font-weight: 600;
  white-space: nowrap;
}

.prosa tr:last-child td {
  border-bottom: 0;
}

/* --- Uebersichten --------------------------------------------------------- */

.abschnitt h1 {
  margin: 0 0 6px;
  font-size: clamp(1.6rem, 3.6vw, 2.05rem);
  letter-spacing: -0.022em;
}

.mag-anriss {
  margin: 0 0 22px;
  color: var(--text-dim);
}

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

.artikel-karte {
  display: block;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color 0.14s ease;
}

.artikel-karte:hover {
  border-color: var(--accent-line);
}

.artikel-datum {
  display: block;
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-ghost);
  margin-bottom: 6px;
}

.artikel-karte b {
  display: block;
  font-size: 0.98rem;
  line-height: 1.35;
  color: var(--text);
  margin-bottom: 6px;
}

.artikel-anriss {
  display: block;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--text-dim);
}

/* Der Ankerlink an den Ueberschriften. Beim Ueberfahren sichtbar, bei
   Tastaturfokus ebenfalls -- ein Element, das nur bei :hover existiert,
   ist fuer Tastaturnutzer nicht vorhanden. */
.anker {
  margin-left: 9px;
  color: var(--text-ghost);
  text-decoration: none;
  font-weight: 400;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.prosa h2:hover .anker,
.prosa h3:hover .anker,
.prosa h4:hover .anker,
.prosa h2:focus-within .anker,
.prosa h3:focus-within .anker,
.prosa h4:focus-within .anker,
.anker:focus,
.anker:focus-visible {
  opacity: 1;
}

.anker:hover {
  color: var(--accent);
}

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

/* Die Marke neben der Wortmarke. Der Abstand als gap am Flex-Container ist
   hier unbedenklich: .mag-logo enthaelt genau zwei Kinder, das SVG und die
   <span> mit dem Wort. Bei bitinformer stand die Wortmarke als blosser
   Textknoten daneben und der gap landete mitten im Wort -- deshalb hier
   die <span>. */
.mag-logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}

.mag-marke {
  flex: 0 0 auto;
  color: var(--text);
}

/* ==========================================================================
   Die Seiten der Hauptseite

   Gegen dieselben Tokens wie die App gebaut. Kein eigenes Farbsystem und
   keine Verlaeufe: das Original hatte auf einer Leistungsseite 23
   eingebettete SVGs mit 27 Farbstopps, und davon traegt keiner Bedeutung.
   ========================================================================== */

.hero {
  padding: 46px 0 40px;
  border-bottom: 1px solid var(--border-soft);
}

.eyebrow {
  margin: 0 0 14px;
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
  color: var(--accent);
}

.hero h1 {
  margin: 0 0 12px;
  font-size: clamp(2.1rem, 6vw, 3.4rem);
  line-height: 1.06;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.hero-sub {
  margin: 0 0 18px;
  font-size: clamp(1.05rem, 2.4vw, 1.32rem);
  line-height: 1.4;
  color: var(--text-dim);
  max-width: 34ch;
}

.hero-text {
  margin: 0 0 26px;
  max-width: 62ch;
  color: var(--text-dim);
}

.hero-knoepfe {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.knopf {
  display: inline-block;
  padding: 11px 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.93rem;
  font-weight: 500;
  text-decoration: none;
}

.knopf:hover {
  border-color: var(--accent-line);
}

.knopf-voll {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--auf-akzent);
  font-weight: 600;
}

.knopf-voll:hover {
  filter: brightness(1.08);
}

.abschnitt {
  padding: 40px 0;
  border-bottom: 1px solid var(--border-soft);
}

.abschnitt:last-child {
  border-bottom: 0;
}

.abschnitt h2 {
  margin: 0 0 10px;
  font-size: clamp(1.35rem, 3vw, 1.75rem);
  letter-spacing: -0.024em;
  line-height: 1.24;
  text-wrap: balance;
}

.fuehrung {
  margin: 0 0 4px;
  max-width: 66ch;
  color: var(--text-dim);
}

/* --- Fallstudien ---------------------------------------------------------- */

.faelle {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 14px;
  margin-top: 18px;
}

.fall {
  padding: 22px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.fall-marke {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  color: var(--accent);
}

.fall h3 {
  margin: 0 0 10px;
  font-size: 1.12rem;
  line-height: 1.3;
  letter-spacing: -0.015em;
}

.fall-problem {
  margin: 0 0 16px;
  color: var(--text-dim);
  font-size: 0.94rem;
}

/* Beschreibungsliste statt Absaetze: "Loesung" und "Ergebnis" sind
   Bezeichner zu einem Inhalt, und genau dafuer ist dl da. Im Original
   standen beide als gleichrangige <p> untereinander, wodurch der
   Zusammenhang nur optisch bestand. */
.fall-liste {
  margin: 0;
  display: grid;
  gap: 4px;
}

.fall-liste dt {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  color: var(--text-ghost);
  margin-top: 10px;
}

.fall-liste dd {
  margin: 0;
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--text-dim);
}

.fall-zahl {
  color: var(--text) !important;
}

.fall-zahl b {
  color: var(--accent);
}

/* --- Leistungen ----------------------------------------------------------- */

.leistungen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 12px;
  margin-top: 18px;
}

.leistung {
  display: block;
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color 0.14s ease;
}

.leistung:hover {
  border-color: var(--accent-line);
}

.leistung h3 {
  margin: 0 0 8px;
  font-size: 1.05rem;
  letter-spacing: -0.015em;
  color: var(--text);
}

.leistung p {
  margin: 0 0 12px;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--text-dim);
}

.mehr {
  font-size: 0.86rem;
  font-weight: 500;
  color: var(--accent);
}

.mehr::after {
  content: " →";
}

/* --- Ablauf --------------------------------------------------------------- */

.ablauf {
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: schritt;
  display: grid;
  gap: 2px;
}

.ablauf li {
  counter-increment: schritt;
  display: grid;
  grid-template-columns: 34px 1fr;
  gap: 14px;
  padding: 14px 0;
  border-top: 1px solid var(--border-soft);
}

.ablauf li::before {
  content: counter(schritt);
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--accent);
  padding-top: 2px;
}

/* Beide in die zweite Spalte, ausdruecklich.

   Ohne das landet die <span> in Zeile zwei, Spalte EINS -- also in den
   34 Pixeln, die fuer die Ziffer gedacht sind. Der Text bricht dann auf
   einen Buchstaben pro Zeile um. Das ist auf der Startseite passiert,
   ohne dass es jemandem aufgefallen waere: bei drei Woertern faellt eine
   schmale Spalte nicht auf, bei drei Zeilen schon. */
.ablauf b,
.ablauf span {
  grid-column: 2;
}

.ablauf b {
  font-size: 0.98rem;
  font-weight: 600;
}

.ablauf span {
  display: block;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--text-dim);
  margin-top: 3px;
}

.ablauf-nach {
  margin: 22px 0 0;
}

/* --- Gruende -------------------------------------------------------------- */

.gruende {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
  margin-top: 20px;
}

.grund {
  padding: 18px;
  background: var(--surface-2);
  border-radius: var(--radius);
}

.grund h3 {
  margin: 0 0 7px;
  font-size: 1rem;
  letter-spacing: -0.012em;
}

.grund p,
.gruende-weiter p {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.58;
  color: var(--text-dim);
}

.gruende-weiter {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 22px;
  margin-top: 26px;
  padding-top: 24px;
  border-top: 1px solid var(--border-soft);
}

.gruende-weiter h4 {
  margin: 0 0 7px;
  font-size: 0.95rem;
  letter-spacing: -0.01em;
}

/* --- Aufruf --------------------------------------------------------------- */

.aufruf {
  text-align: left;
}

.haken {
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 7px;
}

.haken li {
  padding-left: 26px;
  position: relative;
  color: var(--text-dim);
}

/* Der Haken als Pseudo-Element, nicht als Zeichen im Text: so liest ein
   Screenreader nicht "Haken" vor jedem Punkt. */
.haken li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 8px;
  width: 9px;
  height: 5px;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}

.aufruf-knopf {
  margin: 24px 0 0;
}

/* --- Stapel: die Werkzeug- und Technik-Listen ------------------------------

   Die Herstellerzeichen aus dem Original stehen wieder davor, aber klein:
   14 Pixel, so hoch wie die Schrift daneben. In WordPress waren sie so
   gross, dass zwoelf Zeichen die Zeile fuellten und der Name zur
   Bildunterschrift wurde. */

.stapel + .stapel {
  margin-top: 22px;
}

.stapel-titel {
  margin: 0 0 10px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-dim);
}

.chips {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.chips li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 11px 5px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--text-dim);
}

/* Ein Chip ohne Zeichen bekommt links denselben Abstand wie rechts,
   damit die Namen nicht um drei Pixel verspringen. */
.chips li:not(:has(.logo)) {
  padding-left: 11px;
}

/* Beim Ueberfahren tritt der Chip einen Schritt vor: Rahmen im Akzent,
   Grund eine Stufe heller, Name in voller Textfarbe. Die einfarbigen
   Zeichen gehen mit -- sie erben die Textfarbe. Die farbigen bekommen
   etwas mehr Saettigung, damit sie nicht als einzige stehenbleiben.

   In @media (hover: hover) gekapselt: auf einem Fingergeraet gibt es
   kein Ueberfahren, dort bleibt der Zustand nach einer Beruehrung
   haengen, und dann sieht ein Chip aus wie ausgewaehlt, ohne es zu sein.

   KEIN cursor: pointer und kein Anheben. Die Chips sind eine
   Aufzaehlung, keine Knoepfe -- sie duerfen aufmerken, aber nicht
   behaupten, dass ein Klick etwas tut. */
@media (hover: hover) {
  .chips li {
    transition:
      border-color 0.16s ease,
      background-color 0.16s ease,
      color 0.16s ease;
  }

  .chips li:hover {
    border-color: var(--accent-line);
    background: var(--surface-3);
    color: var(--text);
  }

  .logo {
    transition: filter 0.16s ease;
  }

  .chips li:hover .logo {
    filter: saturate(1.2) brightness(1.1);
  }
}

/* Die Zeichen sind Schmuck. Sie tragen aria-hidden, und ihre Groesse
   steht hier statt im SVG.

   Die Farbe steht ausdruecklich NICHT hier: die einfarbigen unter ihnen
   sind auf currentColor gesetzt und erben damit die Textfarbe des Chips.
   So sind sie genau so hell wie der Name daneben -- und beim Ueberfahren
   hellen sie mit auf, ohne dass es dafuer eine zweite Regel braucht. */
.logo {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
}

.chips-frei {
  margin-top: 22px;
}

/* --- Karten ---------------------------------------------------------------

   Wie .leistung, aber ohne Verweis: die meisten dieser Karten fuehren
   nirgendwohin, und ein <a> ohne Ziel ist fuer die Tastatur eine
   Sackgasse. */

.karten {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 12px;
  margin-top: 20px;
}

.karte {
  padding: 18px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
}

.karte h3 {
  margin: 0 0 7px;
  font-size: 1rem;
  letter-spacing: -0.012em;
}

.karte h3 a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--accent-line);
}

.karte h3 a:hover {
  border-bottom-color: var(--accent);
}

.karte p {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.58;
  color: var(--text-dim);
}

.karte p + p {
  margin-top: 12px;
}

/* Die Auszeichnung ueber der Ueberschrift: "Python · Aktiv". */
/* --text-dim, nicht --text-faint: bei 0.74rem kommt --text-faint auf
   surface-2 nur auf 4.35:1 und faellt damit unter die 4.5, die kleiner
   Text braucht. --text-dim schafft 4.71. */
.karte-marke {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px !important;
  font-size: 0.74rem !important;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim) !important;
}

.marke-sprache {
  font-family: var(--mono);
  text-transform: none;
  letter-spacing: 0;
  padding: 2px 7px;
  border-radius: 4px;
  background: var(--surface-3);
  color: var(--text);
}

.marke-neu {
  padding: 2px 7px;
  border-radius: 4px;
  background: var(--accent-bg);
  color: var(--accent-soft);
  font-weight: 600;
}

.mehr-link {
  color: var(--accent-soft);
  text-decoration: none;
  font-weight: 500;
}

.mehr-link:hover {
  text-decoration: underline;
}

/* --- Pfeilliste -----------------------------------------------------------

   Das Dreieck ist ein Pseudo-Element und kein Zeichen im Text: sonst
   liest ein Screenreader vor jedem Punkt "schwarzes Dreieck nach
   rechts". */

.pfeile {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 10px;
}

.pfeile li {
  position: relative;
  padding-left: 22px;
  color: var(--text-dim);
  font-size: 0.93rem;
  line-height: 1.55;
}

.pfeile li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 0.55em;
  border-left: 6px solid var(--accent);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
}

/* --- FAQ ------------------------------------------------------------------

   <details> statt Javascript. Das Zeichen rechts ist ein
   Pseudo-Element -- im Original stand ein "+" als Text in der
   Zusammenfassung, und das las ein Screenreader vor jeder Frage mit. */

.faq {
  margin-top: 20px;
  border-top: 1px solid var(--border-soft);
}

.faq details {
  border-bottom: 1px solid var(--border-soft);
}

.faq summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 16px 0;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.96rem;
  list-style: none;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: "";
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--text-faint);
  border-bottom: 2px solid var(--text-faint);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 0.18s ease;
}

.faq details[open] summary::after {
  transform: rotate(225deg) translate(-2px, -2px);
}

.faq summary:hover {
  color: var(--accent-soft);
}

.faq details p {
  margin: 0 0 16px;
  padding-right: 25px;
  font-size: 0.92rem;
  line-height: 1.62;
  color: var(--text-dim);
}

/* --- Hinweiskasten und Nachsatz -------------------------------------------- */

.hinweis {
  margin-top: 18px;
  padding: 18px;
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  background: var(--accent-bg);
}

.hinweis b {
  display: block;
  margin-bottom: 6px;
  font-size: 0.96rem;
}

.hinweis p {
  margin: 0 0 14px;
  font-size: 0.9rem;
  line-height: 1.58;
  color: var(--text-dim);
}

.hinweis p:last-child {
  margin-bottom: 0;
}

.nachsatz {
  margin: 18px 0 0;
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--text-faint);
}

.nachsatz a {
  color: var(--accent-soft);
}

/* --- Person ---------------------------------------------------------------- */

.person {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: 24px;
}

/* Breite und Hoehe stehen am <img>, damit beim Laden nichts springt.
   aspect-ratio haelt den Zuschnitt, wenn das Bild schmaler wird. */
.person-bild {
  flex: 0 0 auto;
  width: 92px;
  height: 92px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center 22%;
  border: 1px solid var(--border);
}

.person-name {
  margin: 0;
  font-weight: 600;
}

.person-rolle {
  margin: 2px 0 14px;
  font-size: 0.88rem;
  color: var(--text-dim);
}

.person-text p:last-child {
  margin: 0;
}

/* --- Ein schmaler Kopf ----------------------------------------------------

   Impressum, Datenschutz und Kontakt haben keinen Aufmacher, nur einen
   Titel. Der grosse Abstand des Heldenkopfs waere dort eine Behauptung. */

.hero-schmal {
  padding-bottom: 26px;
}

.hero-schmal h1 {
  font-size: clamp(1.7rem, 4vw, 2.4rem);
}

/* --- Rechtstext -----------------------------------------------------------

   Impressum und Datenschutzerklaerung. Bewusst schmal: 4616 Woerter
   ueber die volle Breite liest niemand. 68 Zeichen pro Zeile ist die
   Spanne, in der das Auge die naechste Zeile noch findet. */

.rechtstext {
  max-width: 68ch;
}

.rechtstext h2 {
  margin: 34px 0 10px;
  font-size: 1.22rem;
  letter-spacing: -0.018em;
  line-height: 1.3;
}

.rechtstext h3 {
  margin: 26px 0 8px;
  font-size: 1.02rem;
  letter-spacing: -0.012em;
}

.rechtstext h2:first-child,
.rechtstext h3:first-child,
.rechtstext p:first-child {
  margin-top: 0;
}

.rechtstext p {
  margin: 0 0 16px;
  color: var(--text-dim);
  line-height: 1.72;
}

.rechtstext strong {
  color: var(--text);
  font-weight: 600;
}

.rechtstext ul,
.rechtstext ol {
  margin: 0 0 16px;
  padding-left: 22px;
  color: var(--text-dim);
}

.rechtstext li {
  margin-bottom: 7px;
  line-height: 1.66;
}

/* Die Verweise in der Datenschutzerklaerung sind teils volle Adressen
   (eur-lex.europa.eu/legal-content/...?uri=celex%3A32016R0679) und
   sprengen sonst auf dem Telefon die Zeile. */
.rechtstext a {
  color: var(--accent-soft);
  text-underline-offset: 2px;
  overflow-wrap: anywhere;
}

/* --- Kennzahlen ------------------------------------------------------------ */

.zahlen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin: 0;
}

.zahlen > div {
  padding: 18px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
}

.zahlen dt {
  font-size: clamp(1.4rem, 3.4vw, 1.9rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--accent);
  line-height: 1.1;
}

.zahlen dd {
  margin: 7px 0 0;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--text-dim);
}

/* --- Diagramm --------------------------------------------------------------

   Das SVG bringt seine eigene Hoehe mit (320) und skaliert ueber die
   Breite. Der Kasten faengt schmale Fenster ab: unter etwa 560 Pixeln
   werden die Monatsnamen sonst zu Strichen. */

.diagramm {
  margin-top: 18px;
  padding: 14px 0;
  overflow-x: auto;
}

.diagramm svg {
  display: block;
  min-width: 560px;
}

.legende {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 10px 0 0;
  font-size: 0.84rem;
  color: var(--text-dim);
}

.legende-balken,
.legende-linie {
  display: inline-block;
  flex: 0 0 auto;
}

.legende-balken {
  width: 11px;
  height: 11px;
  border-radius: 2px;
  background: var(--accent);
  opacity: 0.22;
}

.legende-linie {
  width: 16px;
  height: 2.5px;
  border-radius: 2px;
  background: var(--accent);
  margin-left: 12px;
}

/* --- Kundenstimmen --------------------------------------------------------- */

.stimmen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 12px;
  margin-top: 20px;
}

.stimmen blockquote {
  margin: 0;
  padding: 18px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
}

/* Die Anfuehrungszeichen als Pseudo-Element statt im Text: im Original
   standen sie als Zeichen im Absatz, und ein Screenreader liest
   "Anfuehrungszeichen unten" mit. Das <blockquote> sagt schon, dass es
   ein Zitat ist. */
.stimmen blockquote p {
  margin: 0 0 12px;
  font-size: 0.93rem;
  line-height: 1.6;
  color: var(--text-dim);
}

.stimmen blockquote p::before {
  content: "\201E";
}

.stimmen blockquote p::after {
  content: "\201C";
}

.stimmen cite {
  font-style: normal;
  font-size: 0.84rem;
  color: var(--text-faint);
}

.stimmen cite b {
  color: var(--text-dim);
  font-weight: 600;
}

/* --- Erreichbarkeit -------------------------------------------------------- */

.erreichbar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
  margin: 0;
}

.erreichbar > div {
  padding: 18px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
}

.erreichbar dt {
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  color: var(--text-dim);
  margin-bottom: 8px;
}

.erreichbar dd {
  margin: 0;
  line-height: 1.6;
  color: var(--text);
}

.erreichbar a {
  color: var(--accent-soft);
  text-decoration: none;
}

.erreichbar a:hover {
  text-decoration: underline;
}

/* --- Formular --------------------------------------------------------------

   Die Beschriftung steht ueber dem Feld und ist ein echtes <label> mit
   for -- kein Platzhaltertext. Ein Platzhalter verschwindet, sobald
   jemand tippt, und wer dann nicht mehr weiss, was in das Feld gehoert,
   hat Pech. */

.formular {
  max-width: 40rem;
  margin-top: 20px;
}

.feld {
  margin: 0 0 18px;
}

.feld label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.9rem;
  font-weight: 600;
}

.pflicht {
  color: var(--accent);
}

.feld-hinweis {
  display: block;
  margin: -2px 0 6px;
  font-size: 0.8rem;
  color: var(--text-faint);
}

.feld input,
.feld textarea {
  display: block;
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 0.94rem;
}

.feld textarea {
  resize: vertical;
  min-height: 120px;
  line-height: 1.6;
}

.feld input:focus-visible,
.feld textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: transparent;
}

.feld-abschluss {
  margin: 0 0 14px;
}

.feld-abschluss .knopf {
  border: 0;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  padding: 11px 22px;
}

/* Der Honigtopf. Nicht display:none -- manche Spam-Programme erkennen
   das und lassen das Feld dann in Ruhe, womit der Zweck verfehlt waere.
   Stattdessen aus dem Bild geschoben. */
.honigtopf {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --- Karten reagieren jetzt auch --------------------------------------------

   Dieselbe Bewegung wie bei den Chips: Rahmen in den Akzent, Grund eine
   Stufe heller. Auch hier kein Zeiger und kein Anheben -- die meisten
   dieser Karten fuehren nirgendwohin. Die eine, die es tut (Backlink
   Checker), traegt einen richtigen Verweis in der Ueberschrift, und der
   hat seinen eigenen Zeiger. */
@media (hover: hover) {
  .karte,
  .zahlen > div,
  .stimmen blockquote,
  .erreichbar > div {
    transition:
      border-color 0.16s ease,
      background-color 0.16s ease;
  }

  .karte:hover,
  .zahlen > div:hover,
  .stimmen blockquote:hover,
  .erreichbar > div:hover {
    border-color: var(--accent-line);
    background: var(--surface-3);
  }
}

/* Der Fuss traegt jetzt drei Verweise statt einem. Auf schmalen Fenstern
   duerfen sie umbrechen, statt die Zeile zu sprengen. */
.mag-fuss-rechts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  justify-content: flex-end;
}

/* ==========================================================================
   Die Startseite als Produktseite

   Bis hierher war das Magazin ein Textkleid: Aufmacher, Absaetze,
   Karten. Die Startseite soll zeigen, dass hinter cyberscale eine
   Anwendung steht -- also steht das Produkt oben, nicht die
   Selbstbeschreibung.
   ========================================================================== */

/* --- Der Aufmacher mit Produktbild ---------------------------------------- */

.hero-produkt {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 34px;
  align-items: center;
  position: relative;
}

/* Der Schimmer.

   Ein weicher Schein im Akzent hinter der Ueberschrift -- der einzige
   Verlauf auf der ganzen Seite, und der einzige Ort, an dem er etwas
   tut: er hebt den Aufmacher vom Rest ab, ohne eine zweite Farbe
   einzufuehren.

   Als Pseudo-Element und nicht als Hintergrund am Abschnitt: so kann er
   ueber den Rand hinausragen, ohne die Breite der Seite zu aendern.
   pointer-events: none, damit er nichts abfaengt, was darunter liegt. */
.hero-produkt::before {
  content: "";
  position: absolute;
  left: -14%;
  top: -34%;
  width: 62%;
  height: 130%;
  background: radial-gradient(
    closest-side,
    var(--schimmer-innen),
    var(--schimmer-aussen) 55%,
    transparent 78%
  );
  pointer-events: none;
  z-index: 0;
}

.hero-produkt > * {
  position: relative;
  z-index: 1;
}

.hero-text-spalte {
  min-width: 0;
}

.hero-fussnote {
  margin: 14px 0 0;
  font-size: 0.84rem;
  color: var(--text-faint);
}

/* Der leise zweite Knopf. Er soll da sein, aber nicht mit dem ersten
   um Aufmerksamkeit streiten. */
.knopf-leise {
  background: transparent;
  color: var(--text-dim);
}

.knopf-leise:hover {
  color: var(--text);
}

/* --- Der Produktrahmen -----------------------------------------------------

   Das SVG bringt seinen eigenen Fensterrahmen mit (drei Punkte, Titel,
   Trennlinie). Der Rahmen hier setzt es nur ab und gibt ihm einen
   Schatten, damit es auf der Flaeche liegt statt in ihr zu kleben. */

.produkt-rahmen {
  min-width: 0;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
  line-height: 0;
}

.produkt-svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Zwei Spalten erst dann, wenn der Aufmacher auch heraustreten darf --
   dieselbe Schwelle wie unten.

   Dazwischen (900 bis 1160) waere die Bildspalte 441 Pixel breit, und
   ein Dashboard mit drei Kacheln und einer Kurve wird darin zur
   Briefmarke. Untereinander ist es dort 852 Pixel breit und damit
   lesbar. Lieber ein hoher Aufmacher als ein unleserliches Bild. */
@media (min-width: 1160px) {
  .hero-produkt {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: 44px;
  }
}

/* --- Das Zahlenband --------------------------------------------------------

   Dieselben Kacheln wie auf der Case-Study-Seite, nur enger: hier sind
   sie ein Beleg im Vorbeigehen, dort der Inhalt des Abschnitts. */

.zahlenband {
  padding-top: 34px;
}

.zahlenband .zahlen > div {
  padding: 15px 16px;
}

.zahlenband .zahlen dt {
  font-size: clamp(1.25rem, 2.8vw, 1.6rem);
}

.zahlenband .nachsatz {
  margin-top: 12px;
}

.zahlenband .nachsatz a {
  color: var(--accent-soft);
}

/* --- Das Werkzeug-Raster ---------------------------------------------------

   Zehn Kacheln, jede ein Verweis in die App. Anders als .karte sind das
   echte Verweise, also duerfen sie den Zeiger und die Hebung haben --
   hier fuehrt jede Kachel wirklich irgendwohin. */

.werkzeuge {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 10px;
  margin-top: 22px;
}

.werkzeug {
  display: block;
  padding: 16px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
}

.werkzeug-zeichen {
  display: block;
  width: 20px;
  height: 20px;
  color: var(--accent);
  margin-bottom: 10px;
}

.werkzeug b {
  display: block;
  font-size: 0.95rem;
  color: var(--text);
  margin-bottom: 5px;
}

.werkzeug span {
  display: block;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-dim);
}

@media (hover: hover) {
  .werkzeug {
    transition:
      border-color 0.16s ease,
      background-color 0.16s ease,
      transform 0.16s ease;
  }

  .werkzeug:hover {
    border-color: var(--accent-line);
    background: var(--surface-3);
    transform: translateY(-2px);
  }
}

/* Der Aufmacher der Startseite darf breiter sein als der Text darunter.

   Die Huelle haelt 900px, weil Fliesstext darueber schlecht lesbar wird.
   Fuer ein Produktbild gilt das nicht -- ein Dashboard in 440 Pixeln ist
   ein Briefmarke. Ab 1160px Fensterbreite tritt der Aufmacher links und
   rechts um 120px heraus; darunter bleibt er in der Spur, sonst
   schoebe er die Seite auf.

   Nur der Aufmacher und das Werkzeug-Raster, nicht der Fliesstext. */
@media (min-width: 1160px) {
  .hero-produkt,
  .werkzeuge {
    margin-left: -120px;
    margin-right: -120px;
  }

  /* NUR BEITRAEGE MIT TABELLE TRETEN HERAUS.

     Vorher galt das fuer jeden. Die Absicht war richtig -- eine Karte von
     852 Pixeln auf einem 1400er Schirm sieht aus wie ein Zettel in einer
     Halle -- aber der Fliesstext blieb bei 72 Zeichen. Gemessen: Karte
     1092, Text 621, also 235 Pixel Leere auf jeder Seite. Aus dem Zettel
     in der Halle wurde eine leere Karte.

     Von 56 Beitraegen haben 8 eine Tabelle und keiner einen Codeblock.
     Die Klasse setzt der Bau, weil nur er den Inhalt kennt. */
  .artikel-breit {
    margin-left: -120px;
    margin-right: -120px;
  }
}

/* Das Aenderungsdatum steht unter dem Erscheinungsdatum, nicht daneben.

   51 der 56 Beitraege wurden nach dem Erscheinen ueberarbeitet, und wer
   einen Text von Dezember liest, will wissen, ob er noch gilt. In einer
   Zeile mit Datum und Lesezeit ginge die Angabe unter. */
.artikel-aktualisiert {
  display: block;
  margin-top: 4px;
  font-size: 0.8rem;
  color: var(--text-ghost);
}

/* --- Die Autorenbox --------------------------------------------------------

   Steht am Ende des Beitrags, abgesetzt durch eine Linie. Ein Text mit
   Absender ist mehr wert als einer ohne -- und auf einer Seite, die SEO
   verkauft, sollte sichtbar sein, wer hinter den Texten steht. */

.autor {
  display: flex;
  gap: 18px;
  align-items: flex-start;
  margin-top: 38px;
  /* Seitlich dieselben 34 Pixel wie der Textblock, damit Portraet und
     Name auf der Flucht des Fliesstexts stehen. Die Trennlinie darueber
     darf breiter sein -- eine Linie, die etwas abschliesst, soll das
     ganze Feld abschliessen. */
  padding: 26px 34px 0;
  border-top: 1px solid var(--border-soft);
}

.autor-bild {
  flex: 0 0 auto;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center 22%;
  border: 1px solid var(--border);
}

.autor-name {
  margin: 0;
  font-weight: 600;
  font-size: 1rem;
}

.autor-rolle {
  margin: 2px 0 10px;
  font-size: 0.84rem;
  color: var(--text-faint);
}

.autor-text {
  margin: 0 0 12px;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--text-dim);
  max-width: 62ch;
}

.autor-wege {
  display: flex;
  gap: 16px;
  margin: 0;
  font-size: 0.88rem;
}

.autor-wege a {
  color: var(--accent-soft);
  text-decoration: none;
}

.autor-wege a:hover {
  text-decoration: underline;
}

@media (max-width: 640px) {
  .autor {
    margin-left: 20px;
    margin-right: 20px;
  }
}

/* --- Newsletter-Anmeldung --------------------------------------------------

   Steht unter dem Beitrag und auf der Blog-Uebersicht, nicht auf den
   Leistungsseiten: wer dort liest, will ein Angebot, keinen Newsletter.

   Abgesetzt im Akzent-Grund, damit sie sich vom Text abhebt, ohne wie
   ein Werbebanner zu schreien -- derselbe Kasten wie .hinweis auf der
   Tools-Seite. */

.newsletter {
  margin-top: 38px;
  padding: 22px 24px;
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  background: var(--accent-bg);
}

.newsletter h2 {
  margin: 0 0 6px;
  font-size: 1.1rem;
  letter-spacing: -0.014em;
}

.newsletter-text {
  margin: 0 0 16px;
  font-size: 0.92rem;
  line-height: 1.58;
  color: var(--text-dim);
  max-width: 56ch;
}

/* Die Beschriftung ist da, aber nicht zu sehen: das Feld traegt einen
   Platzhalter, der dasselbe sagt. Weglassen ginge nicht -- ein Feld ohne
   <label> ist fuer einen Screenreader namenlos, und ein Platzhalter
   zaehlt nicht als Name. */
.newsletter-form label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.newsletter-zeile {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  max-width: 30rem;
}

.newsletter-zeile input {
  flex: 1 1 14rem;
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 0.94rem;
}

.newsletter-zeile input::placeholder {
  color: var(--text-ghost);
}

.newsletter-zeile input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: transparent;
}

.newsletter-zeile button {
  flex: 0 0 auto;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
}

.newsletter-hinweis {
  margin: 14px 0 0;
  font-size: 0.8rem;
  line-height: 1.55;
  color: var(--text-faint);
  max-width: 62ch;
}

.newsletter-hinweis a {
  color: var(--accent-soft);
}

@media (max-width: 640px) {
  .newsletter {
    margin-left: 20px;
    margin-right: 20px;
  }
}

/* --- Suche und Themenschalter in der Kopfzeile -----------------------------

   Die Suche sass zuerst im Koerper der Blog-Uebersicht. Jetzt steht sie
   in der Leiste und ist damit auf allen 71 Seiten erreichbar statt auf
   einer -- zwei Suchfelder auf derselben Seite waeren eine Zumutung
   gewesen, deshalb ist das alte weg.

   Als Knopf, nicht als dauerhaft offenes Feld: die Leiste traegt bereits
   acht Menuepunkte und den Werkzeug-Knopf. Ein Eingabefeld daneben
   draengt das Menue auf einem 1000 Pixel breiten Bildschirm in die
   zweite Zeile. */

.kopf-knoepfe {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: 8px;
}

.kopf-knopf {
  display: none; /* kopf.js macht sie sichtbar */
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}

.kopf-knopf[hidden] {
  display: none;
}

.kopf-knopf:not([hidden]) {
  display: flex;
}

.kopf-knopf:hover {
  border-color: var(--accent-line);
  color: var(--text);
}

.kopf-knopf:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.kopf-knopf svg {
  width: 17px;
  height: 17px;
}

/* Im dunklen Satz die Sonne, im hellen der Mond: das Zeichen zeigt, wohin
   es geht, nicht wo man ist. Beide liegen im Markup, sichtbar geschaltet
   wird per CSS -- so gibt es keinen Moment, in dem das falsche zu sehen
   ist. */
.thema .mond {
  display: none;
}

:root[data-theme="hell"] .thema .sonne {
  display: none;
}

:root[data-theme="hell"] .thema .mond {
  display: block;
}

/* Die aufgeklappte Suche. Sie haengt unter der Leiste und nicht mitten
   auf dem Bild: die Leiste klebt oben, also ist das der Ort, an dem der
   Blick nach dem Klick ohnehin steht. */
.suchlage {
  border-top: 1px solid var(--border-soft);
  background: var(--surface);
}

.suchlage[hidden] {
  display: none;
}

.suchlage-innen {
  max-width: 1180px;
  margin: 0 auto;
  padding: 14px 26px 18px;
}

.suchzeile {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-faint);
}

.suchzeile:focus-within {
  border-color: var(--accent);
  color: var(--accent);
}

.suchzeile svg {
  flex: none;
  width: 17px;
  height: 17px;
}

.suchzeile input {
  flex: 1;
  min-width: 0;
  padding: 12px 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
}

.suchzeile input:focus {
  outline: none;
}

.suchzeile input::placeholder {
  color: var(--text-faint);
}

/* Ein <label>, das nur der Screenreader hoert. Weglassen ginge nicht --
   ein Feld ohne Label ist namenlos, und ein Platzhalter zaehlt nicht als
   Name. */
.nur-vorlesen {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.such-treffer {
  display: block;
  margin-top: 6px;
  padding: 9px 13px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: var(--text);
}

.such-treffer:hover,
.such-treffer:focus-visible {
  background: var(--surface-2);
  outline: none;
}

.such-treffer:focus-visible {
  box-shadow: inset 0 0 0 2px var(--accent);
}

.such-treffer b {
  display: block;
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1.35;
}

.such-treffer span {
  display: block;
  margin-top: 2px;
  font-size: 0.78rem;
  color: var(--text-faint);
}

/* Die Trefferzahl steht in einem role="status" -- ein Screenreader soll
   mitbekommen, dass sich die Liste geaendert hat, ohne dass jemand
   dorthin navigiert. Deshalb bleibt der Absatz auch leer im Markup
   stehen: ein Element, das erst beim ersten Treffer entsteht, wird
   nicht vorgelesen. */
.suchstand {
  margin: 10px 0 0;
  min-height: 1.4em;
  font-size: 0.86rem;
  color: var(--text-faint);
}

@media (max-width: 600px) {
  .suchlage-innen {
    padding: 12px 18px 16px;
  }
}

/* ==========================================================================
   DER HELLE SATZ

   Die dunklen Token stehen nicht hier -- bauen.mjs zieht sie aus app.css
   und setzt sie oben an diese Datei. Hier stehen nur die Abweichungen
   fuer hell, und zwar unter [data-theme="hell"]: dunkel bleibt der
   Grundzustand.

   WARUM NICHT prefers-color-scheme ALS VORGABE: die Werkzeug-App unter
   app.cyberscale.io ist rein dunkel. Wuerde www dem Systemwunsch folgen,
   saehe jemand mit heller Einstellung eine helle Website und daneben
   eine dunkle App -- derselbe Anbieter, zwei Welten. Solange die App
   nicht mitzieht, ist dunkel die Vorgabe und hell eine bewusste Wahl.
   Umstellen ist eine Zeile in thema.js.

   ZWEI TOKEN SIND NEU und gab es im dunklen Satz gar nicht:
   --band     der Hintergrund der klebenden Kopfzeile. Der stand vorher
              als rgba(13,13,15,.86) fest in der Datei und waere im
              hellen Modus als dunkler Balken stehen geblieben.
   --schimmer der Schein hinter dem Aufmacher, hell schwaecher als
              dunkel -- auf Weiss traegt derselbe Wert viel weiter.

   Der Akzent ist im hellen Satz DUNKLER als im dunklen. #e8590c auf
   Weiss kommt nur auf 3,4:1 und faellt damit unter die Grenze fuer
   Text. Die Marke bleibt dieselbe Farbe, der Text bekommt eine, die man
   lesen kann.
   ========================================================================== */

:root {
  --band: rgba(13, 13, 15, 0.86);
  --auf-akzent: #0d0d0f;
  --schimmer-innen: rgba(232, 89, 12, 0.16);
  --schimmer-aussen: rgba(232, 89, 12, 0.05);
}

:root[data-theme="hell"] {
  --bg: #fbfaf8;
  --surface: #ffffff;
  --surface-2: #f3f1ed;
  --surface-3: #e8e5df;
  --border: #d8d4cc;
  --border-soft: #e7e4dd;

  --text: #1b1a18;
  --text-dim: #55524d;
  --text-faint: #67645e;
  --text-ghost: #85817a;

  --accent: #c2450a;
  --accent-soft: #a63a06;
  --accent-bg: rgba(194, 69, 10, 0.08);
  --accent-line: rgba(194, 69, 10, 0.32);

  --success: #16724a;
  --success-bg: rgba(22, 114, 74, 0.1);
  --warn: #8a5a00;
  --warn-bg: rgba(138, 90, 0, 0.12);
  --danger: #b03028;
  --danger-bg: rgba(176, 48, 40, 0.12);

  --band: rgba(251, 250, 248, 0.88);
  --auf-akzent: #ffffff;
  --schimmer-innen: rgba(194, 69, 10, 0.1);
  --schimmer-aussen: rgba(194, 69, 10, 0.03);

  --shadow: 0 1px 2px rgba(27, 26, 24, 0.06), 0 8px 24px rgba(27, 26, 24, 0.08);
}

/* Beim Umschalten faerbt sich die ganze Seite um. Ohne Uebergang ist das
   ein harter Schnitt; mit einem zu langen wirkt es traege. Wer
   Bewegungsarmut eingestellt hat, bekommt keinen -- dafuer sorgt die
   Regel ganz oben in dieser Datei. */
body.magazin,
.mag-kopf-band,
.artikel,
.karte,
.werkzeug,
.zahlen > div,
.erreichbar > div,
.stimmen blockquote {
  transition:
    background-color 0.18s ease,
    border-color 0.18s ease,
    color 0.18s ease;
}

/* --- Der Gratis-Download auf der Startseite --------------------------------

   Waagrecht, wo Platz ist, untereinander auf dem Handy. Bewusst ruhiger
   als der Audit-Aufruf darunter: er will nichts ausser einem Klick, und
   zwei gleich laute Aufrufe hintereinander heben sich gegenseitig auf. */

.download-karte {
  display: flex;
  align-items: center;
  gap: 28px;
  flex-wrap: wrap;
  padding: 26px 30px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.download-text {
  flex: 1 1 20rem;
  min-width: 0;
}

.download-karte h2 {
  margin: 6px 0 8px;
  font-size: 1.24rem;
}

.download-karte p {
  margin: 0;
  color: var(--text-dim);
}

.download-klein {
  margin-top: 8px !important;
  font-size: 0.84rem;
  color: var(--text-faint) !important;
}

.download-knopf {
  flex: none;
  margin: 0 !important;
}

@media (max-width: 600px) {
  .download-karte {
    padding: 22px 20px;
    gap: 18px;
  }

  .download-knopf,
  .download-knopf .knopf {
    width: 100%;
    text-align: center;
  }
}

/* --- Das Prueffeld im Aufmacher -------------------------------------------

   Feld und Knopf sitzen in einer gemeinsamen Umrandung, damit sie als ein
   Bedienelement gelesen werden und nicht als zwei Dinge nebeneinander.
   Der Rahmen liegt auf der Zeile, nicht auf dem Feld -- sonst haette man
   zwei Rahmen ineinander, sobald der Knopf danebensteht.

   Auf dem Handy bricht der Knopf unter das Feld und nimmt die volle
   Breite. Ein 90 Pixel breiter Knopf neben einem 180 Pixel breiten Feld
   ist auf beiden Seiten zu wenig. */

.hero-pruefen {
  margin: 22px 0 10px;
}

.hero-pruefen-zeile {
  display: flex;
  gap: 8px;
  padding: 7px;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius-sm) + 7px);
  background: var(--surface);
}

.hero-pruefen-zeile:focus-within {
  border-color: var(--accent);
}

.hero-pruefen input {
  flex: 1;
  min-width: 0;
  padding: 11px 13px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font: inherit;
}

.hero-pruefen input:focus {
  outline: none;
}

/* Nicht --text-ghost: das kommt im dunklen Satz auf 2,5:1 gegen die
   Feldflaeche. Ein Platzhalter ist kein Fliesstext, aber dieser traegt
   das erwartete Format -- wer ihn nicht lesen kann, weiss nicht, was
   hineingehoert. */
.hero-pruefen input::placeholder {
  color: var(--text-faint);
}

.hero-pruefen .knopf {
  flex: none;
  white-space: nowrap;
}

/* Die Fussnote traegt jetzt einen Verweis. Ohne eigene Farbe waere er
   nicht als solcher zu erkennen -- der Absatz ist gedaempft gesetzt. */
.hero-fussnote a {
  color: var(--accent-soft);
}

@media (max-width: 560px) {
  .hero-pruefen-zeile {
    flex-wrap: wrap;
  }

  /* Volle Breite und mindestens 44 Pixel hoch. Der Knopf kam mit dem
     geerbten Innenabstand auf 40 -- unter der Groesse, die man mit dem
     Daumen sicher trifft, und das beim Haupt-Aufruf der Seite. */
  .hero-pruefen .knopf {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 46px;
  }
}
