/* devpreview.me
   Monochrome, like the icon. One accent, used sparingly. */

/* A fixed typeface instead of system-ui: otherwise the page looks different
   on every device — SF Pro on the Mac, Segoe UI on Windows, Roboto on a
   phone. Inter lives here (SIL Open Font License, see fonts/LICENSE.txt),
   not at Google — otherwise every page view would be a transmission, and
   the privacy page says no third-party requests. One variable cut covers
   every weight, including the 650 a fixed cut would round down to 600. */
@font-face {
  font-family: 'Inter';
  src: url('fonts/inter-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #ffffff;
  --bg-soft: #f6f6f7;
  --bg-sink: #efeff1;
  --ink: #111113;
  --ink-2: #55555c;
  --ink-3: #8a8a93;
  --line: #e2e2e6;
  --line-2: #d0d0d6;
  --accent: #111113;
  --accent-ink: #ffffff;
  --ok-bg: #f0f7f1;
  --ok-line: #bcd9c1;
  --bad-bg: #fdf2f2;
  --bad-line: #eec9c9;
  --radius: 10px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0e0e10;
    --bg-soft: #17171a;
    --bg-sink: #202024;
    --ink: #f2f2f4;
    --ink-2: #a9a9b2;
    --ink-3: #75757e;
    --line: #26262b;
    --line-2: #34343b;
    --accent: #f2f2f4;
    --accent-ink: #0e0e10;
    --ok-bg: #121c14;
    --ok-line: #2c4a32;
    --bad-bg: #1e1414;
    --bad-line: #4d2a2a;
  }
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

/* Der Fuß gehört ans Ende der Seite, nicht ans Ende des Textes. Auf kurzen
   Seiten — Impressum, Bestätigung — hing er sonst mitten im Bild und darunter
   war Leere. Die Spalte füllt die Höhe, der Inhalt dazwischen dehnt sich.
   dvh statt vh, sonst rechnet Safari mit der eingeklappten Leiste. */
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.65 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* 1 0 auto: wachsen ja, schrumpfen nein — sonst quetscht ein langer Text
   sich zusammen, statt die Seite länger zu machen. */
body > main { flex: 1 0 auto; }

/* margin-inline, nicht margin: sonst gewinnt diese Klasse gegen die
   vertikalen Abstände der Abschnitte weiter unten. */
.wrap { max-width: 1040px; margin-inline: auto; padding: 0 24px; }

:root { --gap-section: clamp(52px, 8vw, 92px); }
.narrow { max-width: 660px; }

h1, h2, h3 { line-height: 1.2; letter-spacing: -0.02em; margin: 0 0 .5em; }
h1 { font-size: clamp(2rem, 5vw, 3.2rem); font-weight: 700; }
h2 { font-size: clamp(1.4rem, 3vw, 1.9rem); font-weight: 650; margin-top: 0; }
h3 { font-size: 1.06rem; font-weight: 650; }
p { margin: 0 0 1em; }
a { color: var(--ink); text-underline-offset: 3px; }
code, kbd { font-family: var(--mono); font-size: .88em; }
code { background: var(--bg-sink); padding: .1em .35em; border-radius: 4px; }
kbd {
  background: var(--bg-sink); border: 1px solid var(--line-2);
  border-bottom-width: 2px; border-radius: 5px; padding: .05em .4em; font-size: .82em;
}
.muted { color: var(--ink-2); }
.tiny { font-size: .82rem; }
.sub { color: var(--ink-2); font-size: 1.05rem; max-width: 62ch; margin-bottom: 0; }
h2 + .sub { margin-top: -.2em; }
.fineprint { color: var(--ink-3); font-size: .85rem; }

/* ---------- chrome ---------- */

.top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; max-width: 1040px; margin: 0 auto; padding: 20px 24px;
}
.brand {
  display: inline-flex; align-items: center; gap: 9px;
  font-weight: 650; text-decoration: none; letter-spacing: -0.02em;
}
.brand img { display: block; }
@media (prefers-color-scheme: dark) { .brand img { filter: invert(1); } }
.brand.small { font-size: .95rem; }
.top nav { display: flex; gap: 22px; font-size: .93rem; }
.top nav a { color: var(--ink-2); text-decoration: none; }
.top nav a:hover { color: var(--ink); }
@media (max-width: 620px) { .top nav { display: none; } }

.bottom { border-top: 1px solid var(--line); margin-top: var(--gap-section); padding: 36px 0 44px; }
.foot-grid { display: flex; justify-content: space-between; gap: 30px; flex-wrap: wrap; }
.foot-grid > div:last-child { display: flex; gap: 22px; align-items: flex-start; flex-wrap: wrap; }
.foot-grid a { color: var(--ink-2); text-decoration: none; font-size: .93rem; }
.foot-grid a:hover { color: var(--ink); }
.bottom .tiny { margin-top: 26px; color: var(--ink-3); }

/* ---------- hero ---------- */

.hero { text-align: center; padding: clamp(28px, 6vw, 60px) 24px clamp(28px, 4vw, 44px); }
/* Als Block, sonst fließt die Pill daneben in dieselbe Zeile und beide
   werden gemeinsam zentriert — dann steht keines von beiden mittig. */
.hero-icon { display: block; margin: 0 auto 22px; }
@media (prefers-color-scheme: dark) { .hero-icon { filter: invert(1); } }
.hero h1 { max-width: 18ch; margin-inline: auto; }
.lede {
  font-size: clamp(1.05rem, 2vw, 1.22rem); color: var(--ink-2);
  max-width: 60ch; margin: 22px auto 32px;
}
.cta-row { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-bottom: 18px; }

.pill {
  display: inline-block; margin: 0 0 18px;
  border: 1px solid var(--line-2); border-radius: 999px;
  padding: 5px 14px; font-size: .8rem; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; color: var(--ink-2);
}

/* --- the three steps to the download --- */
.steps { counter-reset: step; list-style: none; padding: 0; margin: 20px 0; }
.steps li {
  counter-increment: step; position: relative; padding-left: 34px;
  margin-bottom: 11px; color: var(--ink-2); font-size: .95rem;
}
.steps li::before {
  content: counter(step); position: absolute; left: 0; top: 1px;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  font-size: .74rem; font-weight: 700; line-height: 22px; text-align: center;
}

/* --- consent --- */
.check {
  display: flex; gap: 10px; align-items: flex-start;
  margin: 18px 0 0; font-size: .87rem; font-weight: 400;
  color: var(--ink-2); cursor: pointer; line-height: 1.5;
}
.check input {
  flex: none; margin: 2px 0 0; width: 17px; height: 17px;
  accent-color: var(--ink); cursor: pointer;
}
.check span { flex: 1; }

/* ---------- buttons ---------- */

/* Eine Zeile. Wo doch eine Unterzeile hingehört — auf der Bestätigungsseite,
   wo der Knopf die Datei selbst holt — schaltet .stacked auf zwei um. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 13px 26px; border-radius: var(--radius);
  font-weight: 600; font-size: .98rem; text-decoration: none;
  border: 1px solid transparent; cursor: pointer; transition: opacity .15s, background .15s;
}
.btn.primary { background: var(--accent); color: var(--accent-ink); }
.btn.primary:hover { opacity: .86; }
.btn.ghost { border-color: var(--line-2); color: var(--ink); }
.btn.ghost:hover { background: var(--bg-soft); }
.btn.big { padding: 16px 34px; font-size: 1.05rem; }
.btn.full { width: 100%; }

/* Die beiden amtlichen Ladenabzeichen.
   Beide bleiben unveraendert — Apple und Google verlangen das, und
   nachgezeichnet waere ohnehin schlechter. Sie passen zusammen, denn beide
   sind hell mit dunkler Schrift; Apples Grafik bringt Flaeche und Rand schon
   mit, Chromes kommt nackt und durchsichtig.

   Angeglichen wird deshalb nur, was Chrome fehlt, und zwar auf Apples Mass.
   Gemessen an der Grafik, nicht geschaetzt: bei 44 px Hoehe ist Apples Rand
   genau 1,00 px stark und die Ecke 7,5 px rund (10 bzw. 75 px, gemessen an
   einem Rasterbild mit 440 px Hoehe). */
/* store-badge, nicht badge: .badge gibt es weiter unten schon, als
   kleine Marke in der Vorfuehrung. Zwei Bedeutungen unter einem Namen
   haetten sich gegenseitig verstellt. */
.store-badge {
  /* Eine Hoehe, aus der sich alles andere ergibt. Die Zeile im Hero setzt sie
     hoeher, sonst muesste jede der folgenden Zahlen zweimal dastehen. */
  --hoehe: 44px;
  /* Apples Seitenverhaeltnis, aus dem SVG: 156.10054 / 40. Chromes Bild ist
     mit 3.31 flacher, also waere seine Schachtel schmaler geblieben — gleich
     hoch, aber sichtbar kuerzer. Deshalb bekommt sie Apples Breite fest
     vorgegeben und das Bild steht mittig darin. */
  --verhaeltnis: 3.902513;
  display: inline-block;
  line-height: 0;
}
.store-badge img { display: block; height: var(--hoehe); width: auto; }

.store-badge.chrome {
  box-sizing: border-box;
  height: var(--hoehe);
  width: calc(var(--hoehe) * var(--verhaeltnis));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Der Rahmen kommt als SVG, nicht als border.
     Er muss mitwachsen — im Hero ist die Schachtel 52 px hoch, unten 44 —,
     und Apples Rand tut das stufenlos, weil er aus einem SVG stammt. Eine
     CSS-Randstaerke rundet dagegen auf ganze Geraetepunkte: bei 52 px
     verlangt dieselbe Herleitung 1,18 px, und daraus wird 1 oder 2. Genau
     das war der sichtbare Unterschied.
     assets/rahmen.svg traegt Apples gemessene Masse, ist aber selbst
     geschrieben und nicht aus seiner Grafik geloest. Weiss und Schwarz
     stecken darin; hier bleibt nichts einzustellen. */
  background: url('rahmen.svg') center / 100% 100% no-repeat;
}
/* Nicht auf die Schachtel gestreckt, sondern hineingestellt: das Bild behaelt
   sein Verhaeltnis, und der Rand rundherum gibt ihm dieselbe Luft, die Apples
   Grafik schon mitbringt. */
.store-badge.chrome img {
  height: auto; width: auto;
  max-height: calc(100% - 4px);
  max-width: calc(100% - 18px);
}

/* Im Hero stehen die Laeden in einer eigenen Zeile: das ist die Handlung,
   die die Seite will. „See it work" darunter ist der Umweg fuer die, die
   erst sehen wollen.
   Eine eigene Zeile allein genuegte dafuer nicht — ein umrandeter Knopf zieht
   auch untereinander so viel Aufmerksamkeit wie die Abzeichen. Also traegt er
   hier keinen Rahmen mehr und ist kleiner: ein Angebot, keine zweite
   Aufforderung. Nur im Hero. Auf get.php ist derselbe Knopf das Einzige, was
   es dort zu tun gibt, und darf aussehen wie einer. */
.cta-row.stores { margin-bottom: 6px; }
.cta-row.secondary { margin-bottom: 18px; }
.cta-row.secondary .btn {
  border-color: transparent;
  padding: 6px 12px;
  font-size: .88rem;
  color: var(--ink-2);
}
.cta-row.secondary .btn:hover { color: var(--ink); background: var(--bg-soft); }

/* Im Hero groesser als unten: dort tragen sie einen Abschnitt, hier sind sie
   das Ziel der ganzen Seite. Beide bleiben gleich hoch — Chromes Bild zwei
   Punkte kleiner, weil sein Rahmen zwei dazugibt. */
.cta-row.stores .store-badge { --hoehe: 52px; }

/* Mittig, auch wenn sie umbrechen.
   Der Abschnitt ist zweispaltig und klappt bei 880 px um; die beiden
   Abzeichen brauchen zusammen 355 px. Umgebrochen wird deshalb in einem
   schmalen Band knapp ueber 880 px und noch einmal auf sehr schmalen
   Schirmen — zwei Grenzwerte, die man beide treffen muesste und von denen
   jeder beim naechsten Umbau danebenliegt. Zentriert stimmt jeder Fall, und
   ein allein stehendes Abzeichen haengt nicht mehr am linken Rand. */
.store-row {
  display: flex; gap: 12px; flex-wrap: wrap;
  justify-content: center;
  margin: 22px 0 20px;
}

/* Auf schmalen Schirmen untereinander. Hier stand .btn — das traf die
   Abzeichen nicht mehr, seit sie store-badge heissen, und die Regel lief
   still ins Leere. `stretch` waere hier ausserdem falsch: Chromes Schachtel
   hat eine feste Breite und wuerde nicht mitgehen, Apples schon. */
@media (max-width: 520px) {
  .cta-row.stores { flex-direction: column; align-items: center; }
  .store-row { flex-direction: column; align-items: center; }
}
.btn.stacked { flex-direction: column; gap: 2px; }
.btn-sub { font-weight: 450; font-size: .8rem; opacity: .72; }

/* ---------- bands & layout ---------- */

section { margin-top: var(--gap-section); }
/* Der Kopf trennt bereits — die erste Sektion braucht den Abstand nicht
   noch einmal obendrauf. */
main > section:first-child { margin-top: 0; }
.band {
  background: var(--bg-soft); border: 1px solid var(--line);
  border-radius: 16px; padding: clamp(24px, 4vw, 44px); max-width: 1040px;
}
@media (max-width: 620px) { .band { border-radius: 12px; } }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: center; }
@media (max-width: 820px) { .split { grid-template-columns: 1fr; } }
.kicker {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-3); font-weight: 650; margin-bottom: .8em;
}
.big { font-size: 1.22rem; font-weight: 550; letter-spacing: -0.01em; }

/* ---------- raw demo figure ---------- */

.rawdemo { margin: 0; border: 1px solid var(--line-2); border-radius: 10px; overflow: hidden; background: var(--bg); }
.rawdemo-bar { display: flex; gap: 6px; padding: 10px 12px; background: var(--bg-sink); border-bottom: 1px solid var(--line); }
.rawdemo-bar span { width: 10px; height: 10px; border-radius: 50%; background: var(--line-2); }
.rawdemo-text {
  margin: 0; padding: 16px; font-family: var(--mono); font-size: .76rem;
  line-height: 1.5; color: var(--ink-2); white-space: pre-wrap; word-break: break-all;
  max-height: 190px; overflow: hidden;
}

/* ---------- interactive demo ---------- */

.demo { margin-top: 26px; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.tabs {
  display: flex; gap: 2px; padding: 8px; background: var(--bg-soft);
  border-bottom: 1px solid var(--line);
  /* Auf schmalen Schirmen scrollen die Reiter seitwärts — die Leiste dazu
     würde eine graue Kante unter den Reitern stehen lassen. */
  overflow-x: auto; scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  border: 0; background: transparent; color: var(--ink-2); cursor: pointer;
  padding: 7px 14px; border-radius: 7px; font: inherit; font-size: .88rem; font-weight: 550; white-space: nowrap;
}
.tab:hover { background: var(--bg-sink); color: var(--ink); }
.tab.is-on { background: var(--accent); color: var(--accent-ink); }

.demo-panes { display: grid; grid-template-columns: 1fr 1fr; }
@media (max-width: 820px) { .demo-panes { grid-template-columns: 1fr; } }
.pane { min-width: 0; }
.pane + .pane { border-left: 1px solid var(--line); }
@media (max-width: 820px) { .pane + .pane { border-left: 0; border-top: 1px solid var(--line); } }
.pane-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 14px; font-size: .76rem; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em; border-bottom: 1px solid var(--line);
}
.badge {
  background: var(--accent); color: var(--accent-ink); border-radius: 5px;
  padding: 2px 7px; font-size: .68rem; letter-spacing: .05em;
}
.pane-body { height: clamp(230px, 42vh, 340px); overflow: auto; padding: 14px; font-family: var(--mono); font-size: .78rem; line-height: 1.6; }

/* Gestapelt zählt jede Höhe doppelt — zwei volle Bereiche übereinander sind
   auf dem Telefon eine halbe Bildschirmhöhe zu viel. Muss nach der Regel
   oben stehen: gleiche Spezifität, es entscheidet die Position. */
@media (max-width: 820px) { .pane-body { height: 210px; } }
.pane-body.raw {
  margin: 0; color: var(--ink-2);
  /* Umbrechend statt seitlich scrollend — so sieht man die Wand,
     um die es geht, statt nur ihren Anfang. */
  white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere;
}

/* rendered tree */
.rendered .row { display: flex; align-items: flex-start; gap: 5px; white-space: pre; }
.rendered .row:hover { background: var(--bg-soft); }
.rendered .tw { width: 12px; flex: none; cursor: pointer; color: var(--ink-3); user-select: none; }
.rendered .tw.leaf { cursor: default; visibility: hidden; }
.rendered .k { color: var(--ink); font-weight: 600; }
.rendered .s { color: #b3261e; }
.rendered .n { color: #1a56c4; }
.rendered .b { color: #7b1fa2; }
.rendered .z { color: var(--ink-3); }
.rendered .p { color: var(--ink-3); }
.rendered .tag { color: #1b6b3a; }
.rendered .attr { color: #7b1fa2; }
.rendered .cmt { color: var(--ink-3); font-style: italic; }
@media (prefers-color-scheme: dark) {
  .rendered .s { color: #ff8a80; }
  .rendered .n { color: #82b1ff; }
  .rendered .b { color: #ce93d8; }
  .rendered .tag { color: #80cbc4; }
  .rendered .attr { color: #ce93d8; }
}
.rendered table { border-collapse: collapse; font-size: .78rem; width: 100%; }
.rendered th, .rendered td { border: 1px solid var(--line); padding: 4px 8px; text-align: left; white-space: nowrap; }
.rendered th { background: var(--bg-soft); font-weight: 650; }
.rendered .md { font-family: 'Inter', -apple-system, system-ui, sans-serif; font-size: .92rem; }
.rendered .md h1 { font-size: 1.35rem; margin: .2em 0 .5em; }
.rendered .md h2 { font-size: 1.1rem; margin: 1em 0 .4em; }
.rendered .md code { font-size: .85em; }
.rendered .md ul { padding-left: 1.2em; }

.own { border-top: 1px solid var(--line); padding: 12px 14px; background: var(--bg-soft); }
.own summary { cursor: pointer; font-size: .88rem; font-weight: 550; color: var(--ink-2); }
.own summary:hover { color: var(--ink); }
.own textarea {
  width: 100%; margin-top: 12px; min-height: 110px; padding: 11px;
  font-family: var(--mono); font-size: .78rem; line-height: 1.5;
  border: 1px solid var(--line-2); border-radius: 8px;
  background: var(--bg); color: var(--ink); resize: vertical;
}
.detected { font-size: .8rem; color: var(--ink-3); margin: 8px 0 2px; min-height: 1.2em; }

/* ---------- cards ---------- */

.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 28px; }
@media (max-width: 900px) { .cards { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .cards { grid-template-columns: 1fr; } }
.card {
  border: 1px solid var(--line); border-radius: 12px; padding: 22px;
  background: var(--bg);
}
.card.wide { grid-column: 1 / -1; background: var(--bg-soft); }
.card.wide h3 { font-size: 1.25rem; }
.card p { color: var(--ink-2); font-size: .95rem; margin-bottom: .7em; }
.card p:last-child { margin-bottom: 0; }

/* ---------- tick list ---------- */

.ticks { list-style: none; padding: 0; margin: 20px 0 0; columns: 2; column-gap: 40px; }
@media (max-width: 700px) { .ticks { columns: 1; } }
.ticks li {
  break-inside: avoid; padding-left: 26px; margin-bottom: 13px;
  position: relative; color: var(--ink-2); font-size: .95rem;
}
.ticks li::before {
  content: "→"; position: absolute; left: 0; color: var(--ink-3); font-weight: 600;
}
.ticks strong { color: var(--ink); font-weight: 600; }

/* ---------- get / form ---------- */

.get { display: grid; grid-template-columns: 1fr 380px; gap: 44px; align-items: start;
       border: 1px solid var(--line); border-radius: 16px; padding: clamp(24px, 4vw, 44px); }
@media (max-width: 880px) { .get { grid-template-columns: 1fr; gap: 30px; } }
.get-main .btn { margin: 18px 0 14px; }

form label { display: block; font-size: .87rem; font-weight: 600; margin: 14px 0 5px; }
form label .opt { font-weight: 400; color: var(--ink-3); }
input[type=email], textarea {
  width: 100%; padding: 11px 13px; font: inherit; font-size: .95rem;
  border: 1px solid var(--line-2); border-radius: 9px;
  background: var(--bg); color: var(--ink);
}
input[type=email]:focus, textarea:focus, .own textarea:focus {
  outline: 2px solid var(--ink); outline-offset: 1px; border-color: transparent;
}
form textarea { resize: vertical; }
form .btn { margin-top: 18px; }
form .fineprint { margin-top: 12px; }
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.notice { border-radius: 10px; padding: 16px 18px; font-size: .93rem; }
.notice.ok { background: var(--ok-bg); border: 1px solid var(--ok-line); }
.notice.bad { background: var(--bad-bg); border: 1px solid var(--bad-line); }
/* body.plain h1 gibt der Überschrift auf den Textseiten Luft nach oben.
   Im Kasten ist dieselbe Luft ein Loch zwischen Rand und Zeile — und weil
   jene Regel weiter unten steht und gleich schwer wiegt, muss diese hier
   den Kasten ausdrücklich nennen, um sie zu schlagen. */
.notice h1, .notice h3, body.plain .notice h1 { margin-top: 0; }
.notice p:last-child { margin-bottom: 0; }
.notice.standalone { padding: 34px; margin-top: 40px; }
.notice.standalone .btn { margin-top: 14px; }
/* Der Knopf ist das Ziel der Seite und steht allein in seiner Zeile.
   Mittig wirkt er dort weniger wie ein Nachtrag am linken Rand. */
.notice.standalone .act { text-align: center; }

/* Die Beispieldateien. Eine Zeile je Datei, die ganze Zeile anklickbar —
   das Ziel ist, eine davon zu oeffnen, und ein Ziel soll man nicht treffen
   muessen. Die Art steht als Marke davor, damit die Liste beim Ueberfliegen
   nach Formaten sortiert erscheint und nicht nach Dateinamen. */
/* Ueberschrift je Gruppe. Der Untertitel steht in derselben Zeile, klein
   und gedaempft: 21 Dateien untereinander sind eine Aufzaehlung, sechs
   Gruppen mit je einem Satz sind eine Gliederung. */
.samples-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  font-size: .95rem; margin: 26px 0 10px;
}
.samples-head span { font-weight: 400; font-size: .85rem; color: var(--ink-2); }

.samples { list-style: none; padding: 0; margin: 0 0 4px; }
.samples li + li { margin-top: 8px; }
.samples a {
  display: grid;
  /* Feste Mittelspalte, keine automatische. Jedes li ist ein eigenes Raster,
     also berechnet sonst jede Zeile ihre Breite selbst und die Beschreibungen
     stehen ausgefranst — bei fuenf Zeilen mit fuenf Anfaengen. */
  grid-template-columns: 70px 140px 1fr;
  align-items: baseline;
  gap: 0 14px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--bg);
  text-decoration: none;
  color: inherit;
}
.samples a:hover { border-color: var(--accent); background: var(--bg-soft); }
.samples .kind {
  font-size: .68rem; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--accent);
}
.samples .name { font-family: var(--mono); font-size: .9rem; color: var(--ink); }
.samples .what { color: var(--ink-2); font-size: .88rem; }
@media (max-width: 620px) {
  .samples a { grid-template-columns: 70px 1fr; }
  .samples .what { grid-column: 2; margin-top: 3px; }
}

body.plain main { padding-bottom: 40px; }
body.plain h1 { font-size: clamp(1.7rem, 4vw, 2.3rem); margin-top: 40px; }
body.plain h2 { font-size: 1.15rem; margin-top: 2em; }

.selftest td { padding: 5px 14px 5px 0; border-bottom: 1px solid var(--line); font-size: .92rem; }
table.selftest { border-collapse: collapse; width: 100%; margin: 20px 0 24px; }

/* Quelltext in der Vorschau: eine Zeile je Zeile, links die Nummer. Dieselbe
   Anordnung wie in der Erweiterung, nur ohne das Falten — hier geht es um
   das eine, was man in zwei Sekunden sieht: aus einer Zeile werden viele. */
.code-line { display: flex; align-items: baseline; white-space: pre; }
.code-nr {
  flex: none; width: 2.5ch; margin-right: 12px; text-align: right;
  color: var(--ink-3); user-select: none; -webkit-user-select: none;
}
.code-text { flex: 1; min-width: 0; white-space: pre-wrap; word-break: break-word; }
.c-sel { color: #d97706; }
.c-prop { color: #2563eb; }
.c-string { color: #16a34a; }
.c-number { color: #9333ea; }
.c-keyword { color: #dc2626; }
.c-comment { color: var(--ink-3); font-style: italic; }
.c-op { color: var(--ink-3); }

/* ---------- showcase ----------
   Drei Karten, die nicht nur behaupten, sondern zeigen. Ein Absatz über das
   Auseinanderziehen einer Datei ist eine Behauptung; eine Zeile, aus der
   sechs werden, ist der Beweis — und er passt in denselben Platz. */
.showcase {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 28px;
}
@media (max-width: 900px) { .showcase { grid-template-columns: 1fr; } }

.card.show { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.card.show h3 { margin: 20px 22px 0; }
.card.show p { margin: .7em 22px 22px; }

/* Gleiche Höhe für alle drei, damit die Überschriften darunter auf einer
   Linie stehen. Drei Karten, die sich gegenseitig verschieben, sehen aus wie
   ein Fehler, nicht wie drei Antworten. */
.show-art {
  background: var(--bg-soft); border-bottom: 1px solid var(--line);
  padding: 16px 18px 18px;
  /* Feste Höhe, nicht Mindesthöhe: drei Karten, deren Bild verschieden hoch
     ist, verschieben die Überschriften darunter gegeneinander, und das sieht
     aus wie ein Fehler statt wie drei Antworten. */
  height: 248px;
  display: flex; flex-direction: column; justify-content: flex-start;
}

.art-label {
  margin: 0 0 6px !important; font-size: .68rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-3);
}
.art-label + * + .art-label { margin-top: 14px !important; }

.art-before {
  display: block; font-family: var(--mono); font-size: .66rem; line-height: 1.5;
  color: var(--ink-2); background: var(--bg); border: 1px solid var(--line);
  border-radius: 6px; padding: 7px 9px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.art-after {
  display: flex; flex-direction: column;
  font-family: var(--mono); font-size: .68rem; line-height: 1.55;
  color: var(--ink-2); white-space: pre;
}
.art-after i {
  display: inline-block; width: 1.4ch; margin-right: 9px;
  color: var(--ink-3); font-style: normal;
}
.art-after b { font-weight: 400; }

.swatches { display: flex; gap: 5px; }
.swatches span {
  flex: 1; height: 34px; border-radius: 5px;
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / .08);
}

.art-facts { display: flex; flex-direction: column; gap: 4px; font-size: .72rem; }
.art-facts span { color: var(--ink-2); font-family: var(--mono); }
.art-facts i {
  display: inline-block; width: 8.5em; color: var(--ink-3); font-style: normal;
}
.art-facts b { font-weight: 600; }
.art-facts .ok { color: #059669; }
.art-facts .bad { color: #d97706; }

table.mini { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: .68rem; }
table.mini td { padding: 3px 0; color: var(--ink-2); white-space: nowrap; }
table.mini td:nth-child(2) { color: var(--ink-3); padding-left: 10px; }
table.mini td:last-child { text-align: right; }
.ret-promise { color: #d97706; }
.ret-self { color: #4f46e5; }
.ret-none { color: var(--ink-3); }
.ret-value { color: #059669; }

/* ---------- Behauptungen ----------
   Zwölf Zeilen statt zwölf Kästen.
   Jeder Rahmen kostet Platz und sagt „hier fängt etwas Neues an" — zwölfmal
   hintereinander heisst das gar nichts mehr, und dazwischen steht jeweils
   ein Absatz. Ohne Rahmen, mit einer fetten Zeile davor, liest man die Liste
   in zwanzig Sekunden durch, statt an ihr abzurutschen. */
.claims {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 2px 48px; margin-top: 30px;
}
@media (max-width: 760px) { .claims { grid-template-columns: 1fr; } }

.claim { padding: 16px 0; border-top: 1px solid var(--line); }
.claim b { display: block; margin-bottom: 4px; font-size: 1rem; color: var(--ink); }
.claim span { display: block; color: var(--ink-2); font-size: .92rem; line-height: 1.55; }

/* Die eine grosse Karte darüber. Sie darf breit sein, weil sie die einzige
   ist — zwei „wide" nebeneinander waren wieder eine Wand, nur in gross. */
.card.feature { margin-top: 16px; background: var(--bg-soft); }
.card.feature h3 { font-size: 1.3rem; }

/* Der Punkt-me in der Wortmarke tritt zurück. In einer Farbe gesetzt liest
   sich der Name wie eine Adresse in einer Fußzeile; zweifarbig ist er ein
   Name, der zufällig auch dorthin führt. */
.tld { font-style: normal; color: var(--ink-3); }
