/* ══════════════════════════════════════════════════════════════════════════
   POSTD · PLAKAT — Website. Baut auf tokens.css + components.css.
   Zwei Gitter, eine Zahl: zwölf. Inhaltsgitter eingerückt mit Stegen,
   Kachelgitter randlos ohne Stege. (§02)
   ══════════════════════════════════════════════════════════════════════════ */

/* KEIN scroll-behavior:smooth — das Smooth Scrolling macht motion.js (D17).
   Beides gleichzeitig glättet doppelt und die zwei Regler kämpfen. */
body{ overflow-x:hidden; }

/* ── Inhaltsgitter ───────────────────────────────────────────────────────── */
.stage{
  width:100%; max-width:var(--stage-max); margin:0 auto;
  padding-inline:var(--edge-pad);
}
.grid{
  display:grid; grid-template-columns:repeat(12,1fr); gap:var(--gutter);
}
/* Die fünf erlaubten Aufteilungen — eine sechste gibt es nicht. */
.s-12 > *{ grid-column:span 12; }
.s-7-5  > *:nth-child(odd){ grid-column:span 7; } .s-7-5  > *:nth-child(even){ grid-column:span 5; }
.s-6-6  > *{ grid-column:span 6; }
.s-4-4-4 > *{ grid-column:span 4; }
.s-2-10 > *:nth-child(odd){ grid-column:span 2; } .s-2-10 > *:nth-child(even){ grid-column:span 10; }
@media (max-width:1023px){
  .s-7-5 > *, .s-6-6 > *, .s-2-10 > *{ grid-column:span 12; }
  .s-4-4-4 > *{ grid-column:span 4; }
}
@media (max-width:767px){ .grid > *{ grid-column:span 12 !important; } }

/* ── Takt ────────────────────────────────────────────────────────────────── */
.section{ padding-block:var(--beat); }
.section-tight{ padding-block:var(--sp-8); }
.measure{ max-width:var(--measure); }

/* Typografie: pro Fläche ein Display-Grad + ein Mono-Label */
.d1{ font-size:clamp(48px,7.4vw,96px); line-height:.92; letter-spacing:-.038em; font-weight:700; }
/* F8: mobil genau drei Zeilen statt vier. 48px brachen die Zeile viermal. */
@media (max-width:767px){ .d1{ font-size:34px; letter-spacing:-.03em; } }
.d2{ font-size:clamp(34px,4.2vw,56px); line-height:.96; letter-spacing:-.032em; font-weight:700; }
.d3{ font-size:clamp(24px,2.4vw,34px); line-height:1.06; letter-spacing:-.028em; font-weight:700; }
.lead{ font-size:21px; line-height:1.5; color:var(--ink-2); }
.body{ font-size:17px; line-height:1.6; color:var(--ink-2); }
.small{ font-size:14px; line-height:1.5; color:var(--ink-2); }

/* R1.3: Das Strich-Design ist raus — es wirkte wie PowerPoint. Übrig bleibt
   nur das Mono-Label über der Überschrift, ohne Linie, ohne Nummer. */
.kicker{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.16em;
  /* T13 · --acc-700 erreichte auf --bone nur 4,49:1 bei 11 px. */
  text-transform:uppercase; color:var(--acc-800); margin-bottom:18px;
}

/* ══════════════════════════════════════════════════════════════════════════
   Zone A · Kopf — Zeichen links, Pillen rechts, KEINE Mitte.
   Schwebt ohne Trennlinie über dem Feld.
   ══════════════════════════════════════════════════════════════════════════ */
/* Sticky, damit er beim Öffnen des Menüs an jeder Scrollposition stehen
   bleibt — das Menü fährt darunter hervor (R1.12). */
/* T10 · Sprunglink. Ohne ihn muss sich jeder Tastaturnutzer auf jeder Seite
   erneut durch Menuetaste, Funktionen, Galerie, Preise und Editor oeffnen
   tabben, bevor er am Inhalt ist. Sichtbar nur bei Fokus, damit die
   Kopfleiste optisch unveraendert bleibt. */
.skip{
  position:absolute; left:var(--edge-pad); top:-100px; z-index:200;
  display:inline-flex; align-items:center; height:44px; padding:0 20px;
  background:var(--ink); color:var(--paper); border:0; border-radius:var(--r-control);
  font-family:var(--font-display); font-size:15px; font-weight:600; text-decoration:none;
  transition:top .12s;
}
.skip:focus{ top:16px; }
@media (prefers-reduced-motion:reduce){ .skip{ transition:none; } }

.head{
  position:sticky; top:0; z-index:60;
  height:76px; display:flex; align-items:center; justify-content:space-between;
  gap:var(--sp-4); padding-inline:var(--edge-pad);
  background:var(--paper);
}
.head-l{ display:flex; align-items:center; gap:10px; }
.pills{
  display:flex; align-items:center; gap:5px;
  background:rgba(255,255,255,.6); padding:5px; border-radius:var(--r-control);
  backdrop-filter:blur(6px);
}
/* M05/M16 · Zwei Befunde, eine Loesung. Am Schreibtisch konkurrierte die
   Taste im Kopf mit der Haupttaste im Hero — zwei gleich laute Aktionen im
   selben Bild erzwingen eine Entscheidung, die niemand treffen will. Am Handy
   fehlte umgekehrt jede Handlung in der Kopfleiste, auf Seiten von bis zu
   19.900 Bildpunkten Laenge. Jetzt tritt die Kopf-Taste zurueck, solange der
   Hero sichtbar ist, und kommt danach auf jedem Geraet. */
.head .pills{ transition:opacity var(--t-state), transform var(--t-state); }
/* NACHGEZOGEN 01.08. (AJ): Vorher war die Taste im Hero-Bereich komplett ausgeblendet
   (opacity:0, pointer-events:none). Auf jeder Unterseite steht sie im Kopf, nur auf der
   Startseite fehlte sie — genau dort, wo die meisten ankommen, und man sucht sie.
   Der Grund von M05/M16 bleibt aber richtig: "Kostenlos starten" im Hero fuehrt auf
   dasselbe Ziel, zwei gleich laute Tasten im selben Bild erzwingen eine Entscheidung.
   Deshalb ist sie jetzt DA, aber leise — und wird laut, sobald der Hero weg ist. */
body.hero-oben .head .pill-primary{
  background:var(--paper); color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--ink);
}
body.hero-oben .head .pill-primary:hover{ background:var(--bone); }
body.hero-oben .head .pill-primary .dot{ background:var(--bone); color:var(--ink); }
.head .pill-primary, .head .pill-primary .dot{ transition:background var(--t-state), color var(--t-state), box-shadow var(--t-state); }
@media (max-width:767px){
  .pills{ gap:0; background:none; padding:0; }
  /* Am Handy traegt nur die Haupttaste, der Rest steht im Menue. */
  .pills .pill-quiet{ display:none; }
}
@media (prefers-reduced-motion:reduce){ .head .pills{ transition:none; } }

/* Vollbild-Menü (D9) — Kachelfeld läuft dahinter weiter.
   R1.12: Das Menü FÄHRT VON OBEN unter dem stehenden Kopf hervor. Es blendet
   nicht ein und überdeckt den Morph nicht; der Hamburger springt nie, weil
   der Kopf gar nicht Teil des Menüs ist. */
.menu{
  position:fixed; inset:0; z-index:40;
  background:var(--paper); padding:var(--edge-pad);
  display:flex; flex-direction:column;
  transform:translateY(-100%);
  /* Getrennte Kurven: rein weich ausrollend (out-quint), raus zuegig
     anziehend (in-quint). Eine Kurve fuer beide Richtungen fuehlt sich in
     einer Richtung immer falsch an. */
  transition:transform 620ms cubic-bezier(.22,1,.36,1), visibility 620ms;
  visibility:hidden;
}
.menu.open{ transform:translateY(0); visibility:visible;
  transition:transform 680ms cubic-bezier(.16,1,.3,1), visibility 0s; }
/* Das Blatt bekommt eine eigene Compositing-Ebene, solange es faehrt. Ohne das rechnet
   Safari die Bewegung auf der Haupt-Ebene mit — zusammen mit den Dutzenden dauerhaft
   animierten Kacheln darin wird die Fahrt sichtbar unruhig. Nur waehrend "open", sonst
   haelt der Browser die Ebene dauerhaft vor. */
.menu.open{ will-change:transform; }
/* Waehrend das Blatt faehrt, stehen die Kacheln still. Sie laufen in Endlosschleife
   (tfA–tfD) und konkurrieren sonst mit der Transition um dieselben Frames. Nach der
   Fahrt laufen sie weiter — die Verzoegerung deckt die 680 ms ab. */
.menu .tilefield span.on{ animation-play-state:paused; }
.menu.open .tilefield span.on{ animation-play-state:running; animation-delay:.7s; }
@media (prefers-reduced-motion:reduce){
  .menu.open{ will-change:auto; }
  .menu .tilefield span.on, .menu.open .tilefield span.on{ animation:none; }
}
/* Der Kopf liegt ÜBER dem Menü und bleibt stehen. */
.head{ z-index:60; }
/* b3 (AJ) · Das Menü bekommt den Fokus, damit die Tastatur einen Einstieg hat.
   Sichtbar sein soll das nicht — es ist ein Container, kein Bedienelement. */
.menu:focus{ outline:none; }
/* b3 (AJ) · Solange das Menü offen ist, sind die Pillen im Kopf doppelte Navigation:
   dieselben Ziele stehen darunter groß. Die Kauf-Pille bleibt, sie führt woandershin. */
body.menu-open .pills .pill-quiet{ opacity:0; pointer-events:none; transition:opacity .2s; }
.menu-rows{ margin-top:auto; margin-bottom:auto; position:relative; }
/* Zeilen kommen gestaffelt nach, sobald das Blatt sitzt. */
.menu-rows a{ opacity:0; transform:translateY(16px);
  transition:opacity 300ms cubic-bezier(.4,0,1,1), transform 300ms cubic-bezier(.4,0,1,1); }
.menu.open .menu-rows a{ transition:opacity 520ms cubic-bezier(.16,1,.3,1), transform 520ms cubic-bezier(.16,1,.3,1); }
.menu.open .menu-rows a{ opacity:1; transform:none; }
.menu.open .menu-rows a:nth-child(1){ transition-delay:.10s }
.menu.open .menu-rows a:nth-child(2){ transition-delay:.16s }
.menu.open .menu-rows a:nth-child(3){ transition-delay:.22s }
.menu.open .menu-rows a:nth-child(4){ transition-delay:.28s }
@media (prefers-reduced-motion: reduce){
  .menu{ transition:none } .menu-rows a{ opacity:1; transform:none; transition:none }
}
.menu-rows a{
  display:block; border:0; font-size:46px; line-height:1.18; font-weight:700;
  letter-spacing:-.03em; color:var(--ink); padding:6px 0;
  transition:color var(--t-state);
}
.menu-rows a:hover{ color:var(--loud); }
/* M03 · Das Kachelfeld ist position:absolute mit z-index:0 und malt damit
   ueber jedes nicht positionierte Element. .menu-rows hat position:relative
   und lag deshalb darueber, die Fusszeile des Menues nicht — AGB und Widerruf
   verschwanden vollstaendig hinter einem orangen Quadrat, Datenschutz war
   angeschnitten. Pflichtangaben, die man nicht sieht, sind praktisch nicht
   vorhanden, und am Handy ist das Menue der einzige Navigationsweg. */
.menu-foot{
  position:relative; z-index:1;
  display:flex; justify-content:space-between; align-items:end; gap:var(--sp-4);
  flex-wrap:wrap; border-top:var(--b-inner) solid var(--ink); padding-top:20px;
}
.menu-foot .lnks{ display:flex; gap:18px; flex-wrap:wrap; }
.menu-foot .lnks a{ border:0; color:var(--ink-2); font-size:14px; }
.menu-foot .lnks a:hover{ color:var(--ink); }

/* ══════════════════════════════════════════════════════════════════════════
   Hero — vier Zonen. Mission auf 30 %, nicht 50 %.
   ══════════════════════════════════════════════════════════════════════════ */
/* Der Hero ist INHALTSGETRIEBEN, nicht viewporthoch. Grund: die Mission sitzt
   laut Dokument auf 30 % Höhe, darunter füllte dort das Belegband den Raum.
   Das Belegband ist jetzt ein eigener Block (R1.2) — bei fixer Viewport-Höhe
   entstand darum eine Lücke von ~570 px. Jetzt bestimmt der Abstand die Höhe. */
/* F1 (AJ): der Hero fuellt breit aus, ist aber zwei Kachelreihen duenner als
   volle Schirmhoehe — bei 8 Spalten ist eine Reihe so hoch wie eine Zelle
   (Breite/8), zwei Reihen sind also ~2/8 der Breite. Das Kachelfeld bleibt
   randlos, die Mission optisch mittig, der Anschnitt auf der Faltkante. */
/* f1 (AJ) · Der obere Teil war zu knapp — eine Kachelreihe mehr.
   Gemessen war die Hoehe von der Untergrenze 560 bestimmt, nicht vom
   Viewport-Term: bei 1512 px Breite und rund 830 px Hoehe kam die Rechnung
   auf 380 und die Untergrenze gewann. Eine Aenderung nur am Abzug haette also
   gar nichts bewirkt. Deshalb beides: die Untergrenze waechst um genau eine
   Zelle (Breite/Spalten), und abgezogen wird nur noch eine Reihe statt zwei. */
.hero{ position:relative; display:flex; flex-direction:column; overflow:hidden;
  min-height:max(calc(560px + (100vw/8)), calc(100dvh - var(--hd-h,72px) - (100vw/8))); }
@media (max-width:1023px){ .hero{ min-height:max(calc(520px + (100vw/6)), calc(100dvh - var(--hd-h,72px) - (100vw/6))); } }
@media (max-width:767px){ .hero{ min-height:max(460px, calc(100dvh - var(--hd-h,72px) - 100vw/4)); } }
.hero-in{ position:relative; z-index:10; flex:1; display:flex; flex-direction:column; justify-content:center; }

/* Zone B · Mission — die EINZIGE zentrierte Schrift im System.
   Steht im Fluss: der Abstand nach oben setzt sie hoch (Plakat-Haltung), der
   Abstand nach unten ist gesetzt statt emergent. */
.mission{
  padding-top:clamp(40px, 9vh, 104px);
  padding-inline:8%;
  text-align:center; position:relative; z-index:10;
}
.mission h1{ max-width:22ch; margin:0 auto; }
.mission .cta{ display:flex; gap:12px; justify-content:center; margin-top:var(--sp-5); flex-wrap:wrap; }
/* F3 (AJ): Kontrast, OHNE den Hintergrund durchsichtig zu machen. Die orange
   Primaerpille verschwand auf orangen Kacheln (Flaeche = Flaeche). Beide Pillen
   bekommen hier ihren EIGENEN deckenden Grund: Ink mit Weiss (18,9:1) und
   Papier mit Ink (18,9:1). Damit tragen sie ueber jeder Kachel, egal welche
   Farbe darunter liegt. Gilt nur im Hero — auf ruhigen Flaechen bleibt Orange
   die Primaerfarbe. */
/* Zwei Ursachen, zwei Antworten — Orange bleibt, wie es die Markenregel
   verlangt:
   1) Die Pille ging auf orangen Kacheln unter (Flaeche = Flaeche). Ein
      deckender weisser Ring trennt sie vom Untergrund, ohne den Hintergrund
      anzufassen.
   2) Weiss auf Orange misst nur 3,37:1 und reisst Farbgesetz 2. Die Schrift
      wird Ink: 5,61:1 auf Orange. */
/* M08 · Die Farbregel ist seit Block C der Normalfall, hier bleibt nur der
   Ring: der Hero liegt auf dem Kachelfeld, und eine orange Taste auf einer
   orangen Kachel verliert sonst ihre Kontur. Der Ring ist Absicht, kein
   Pflaster — er trennt Figur von Grund auf einem gemusterten Untergrund. */
.mission .cta .pill-loud{ box-shadow:0 0 0 4px var(--paper); }
.mission .cta .pill-outline{ background:var(--paper); box-shadow:0 0 0 4px var(--paper); }
/* Seit der Hero den Bildschirm fuellt, liegt die Zeile auf Orange: --ink-3 kam
   dort auf 1,63:1 und war unsichtbar. Ink traegt auf beiden Gruenden
   (5,61:1 auf Orange, 18,9:1 auf Weiss). */
.mission .hint{ margin-top:18px; font-family:var(--font-mono); font-size:11px; letter-spacing:.12em; text-transform:uppercase; color:var(--ink); font-weight:500; }
/* M04 · Dieselbe Begruendung gilt fuer jedes Label in der Mission, nicht nur
   fuer die Hinweiszeile. Auf der Manifest-Seite stand das Label in der
   Akzentfarbe und lag zur Haelfte auf einer orangen Kachel — lesbar blieb
   „MANI", „FEST" verschwand. Weil das Kachelfeld je nach Breite anders faellt,
   trat der Fehler nur auf manchen Geraeten auf. Regel fuer das ganze System:
   Loud steht nie auf Loud, ueber dem Kachelfeld traegt Text --ink. */
.mission .kicker{ color:var(--ink); }

/* M14 · Eine Anweisung, die das Geraet nicht ausfuehren kann, ist schlimmer
   als keine. Die Unterscheidung laeuft ueber die Zeigerart, nicht ueber die
   Fensterbreite — ein Touch-Laptop ist breit und hat trotzdem keinen Hover. */
.nur-touch{ display:none; }
@media (hover:none),(pointer:coarse){
  .nur-maus{ display:none; }
  .nur-touch{ display:inline; }
}
@media (max-width:767px){ .mission{ padding-top:var(--sp-7); padding-inline:0; } }

/* Zone C · Beleg — Kundennamen als Schrift, nicht als Logodatei */
.proof{ position:absolute; left:0; right:0; bottom:19%; z-index:10; text-align:center; }
.proof .lbl{ font-family:var(--font-mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--ink-2); }
.proof .row{
  display:flex; justify-content:center; flex-wrap:wrap; gap:34px;
  margin-top:34px; font-size:14px; font-weight:600; color:var(--ink-2);
}
@media (max-width:767px){ .proof{ position:static; padding-bottom:var(--sp-6); } .proof .row{ gap:18px; margin-top:16px; } }

/* Zone D · Anschnitt — drei Panels ragen in den Hero. Der Abstand nach oben
   ist gesetzt (nicht „was übrig bleibt"), damit keine Lücke entsteht. */
.crop{
  position:relative; z-index:10;
  margin-top:auto;                      /* schiebt den Anschnitt an die Faltkante */
  padding-inline:var(--edge-pad);
  display:grid; grid-template-columns:repeat(3,1fr); gap:12px;
  height:64px;
}
.crop > *{ border-radius:var(--r-panel) var(--r-panel) 0 0; }

/* ══════════════════════════════════════════════════════════════════════════
   Bausteine
   ══════════════════════════════════════════════════════════════════════════ */
/* Merkmal-Zeile */
.frow{ display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-7); align-items:center; }
.frow.rev > *:first-child{ order:2; }
@media (max-width:1023px){ .frow{ grid-template-columns:1fr; gap:var(--sp-5); } .frow.rev > *:first-child{ order:0; } }
.eyebrow{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--acc-800); margin-bottom:16px;
}
/* Titel→Text 20, Text→Knopf 32 — immer */
.frow h2 + p, .t20{ margin-top:20px; }
.t32{ margin-top:32px; }

/* Echte Arbeit: Kacheln im 4:5 des Produkts */
.work{ display:grid; grid-template-columns:repeat(5,1fr); gap:var(--gutter); }
.work img{ width:100%; aspect-ratio:4/5; object-fit:cover; border-radius:var(--r-content); }
@media (max-width:1023px){ .work{ grid-template-columns:repeat(3,1fr); } .work > *:nth-child(n+4){ display:none; } }
@media (max-width:767px){ .work{ grid-template-columns:repeat(2,1fr); } .work > *:nth-child(n+3){ display:none; } }

/* Preise: vier Wege */
.plans{ display:grid; grid-template-columns:repeat(4,1fr); gap:14px; align-items:stretch; }
/* M12 · Am Handy stapeln die Karten, und Reihenfolge wirkt dort wie eine
   Empfehlung. Free stand vorn und allein im Bild, das empfohlene Abo kam erst
   nach einem vollen Bildschirm — wer Free zuerst und ohne Vergleich sieht,
   nimmt Free. Ausserdem fehlt ohne Nebeneinander der Ankerpreis, an dem sich
   6,99 EUR als guenstig einordnen laesst. Am Schreibtisch bleibt die Ordnung
   unveraendert, dort sieht man alle vier auf einen Blick. */
@media (max-width:767px){
  .plans{ grid-template-columns:1fr; }
  .plans .plan.feat{ order:-1; }
}
.plan{
  display:flex; flex-direction:column; background:var(--paper);
  border:var(--b-inner) solid var(--ink); border-radius:var(--r-content);
  padding:var(--sp-4);
}
.plan.feat{ background:var(--bone); position:relative; }
.plan .badge{
  position:absolute; top:-11px; left:var(--sp-4);
  /* T04 · war color:var(--paper) und damit 3,37:1 bei 10 px Schriftgroesse. */
  background:var(--loud); color:var(--ink);
  font-family:var(--font-mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  padding:5px 11px; border-radius:var(--r-control);
}
/* M13 · Mono-Label mit Linie statt Abzeichen. Vier ruhige Zusagen wiegen
   mehr als bunte Siegel, und sie passen zur Haltung der Seite. */
.trustrow{
  list-style:none; margin:0; padding:16px 0 0; border-top:var(--b-hair) solid var(--hair);
  display:flex; flex-wrap:wrap; gap:8px var(--sp-4);
  font-family:var(--font-mono); font-size:10.5px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--ink-3);
}
.trustrow li{ display:flex; align-items:center; gap:8px; }
.trustrow li::before{ content:''; width:6px; height:6px; background:var(--loud); flex:none; }
.plan .nm{ font-weight:700; font-size:16px; }
.plan .why{ font-size:14px; color:var(--ink-2); margin-top:5px; }
/* Umschalter monatlich/jaehrlich in der Abo-Karte. Segmentierte Leiste statt einer
   fuenften Karte: das Jahresabo ist eine Zahlungsweise, kein eigener Weg. Startet
   per [hidden] und wird vom Skript nur eingeblendet, wenn checkoutYearUrl gesetzt ist. */
.plan .cyc{
  display:flex; gap:3px; margin-top:14px; padding:3px;
  background:var(--paper); border:var(--b-hair) solid var(--hair); border-radius:var(--r-control);
}
.plan.feat .cyc{ background:var(--paper); }
.plan .cyc button{
  flex:1; padding:7px 4px; border:0; border-radius:var(--r-control); background:none;
  color:var(--ink-2); font-family:inherit; font-size:12.5px; font-weight:600;
  cursor:pointer; white-space:nowrap; transition:background .15s, color .15s;
}
.plan .cyc button.on{ background:var(--ink); color:var(--paper); }
.plan .cyc .sv{ color:var(--loud); font-weight:700; }
.plan .cyc button.on .sv{ color:var(--loud); }
.plan .cyc button:focus-visible{ outline:2px solid var(--loud); outline-offset:2px; }
.plan .price{ font-size:34px; font-weight:700; letter-spacing:-.03em; margin-top:16px; }
.plan .price small{ font-size:14px; font-weight:400; color:var(--ink-2); letter-spacing:0; }
.plan ul{ list-style:none; margin:18px 0 0; padding:0; display:grid; gap:8px; font-size:14px; color:var(--ink-2); }
.plan .pill{ margin-top:20px; width:100%; }
.plan .grow{ flex:1; }
@media (max-width:1023px){ .plans{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:600px){ .plans{ grid-template-columns:1fr; } }

/* Laut-Band als Abschluss */
.band{ background:var(--loud); color:var(--paper); padding:var(--sp-8) var(--edge-pad); }
.band h2{ max-width:22ch; }
.band .pill-quiet{ background:var(--paper); color:var(--ink); }

/* Fuß */
.foot{ border-top:var(--b-block) solid var(--ink); padding-block:var(--sp-6) var(--sp-5); }
.foot-cols{ display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:var(--gutter); }
@media (max-width:767px){ .foot-cols{ grid-template-columns:1fr 1fr; } }
/* T15 · Die Spaltentitel waren h6, waehrend der letzte Inhaltstitel darueber
   h2 war. Vier uebersprungene Ebenen lesen sich in der Ueberschriftenliste
   eines Screenreaders wie eine Luecke. Ebene und Aussehen sind jetzt getrennt:
   h2 traegt die Struktur, .foot-h das Mono-Label. */
.foot h6, .foot .foot-h{
  font-family:var(--font-mono); font-size:10px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3); margin:0 0 14px; font-weight:400;
}
.foot a{ display:block; border:0; color:var(--ink-2); font-size:14px; padding:5px 0; }
.foot a:hover{ color:var(--ink); }
.foot-bar{
  display:flex; justify-content:space-between; gap:var(--sp-4); flex-wrap:wrap;
  margin-top:var(--sp-6); padding-top:18px; border-top:var(--b-hair) solid var(--hair);
  font-family:var(--font-mono); font-size:11px; letter-spacing:.06em; color:var(--ink-3);
}

/* ══════════════════════════════════════════════════════════════════════════
   Marken-Laufband (R1.2) — eigener Block auf Weiß, direkt unter dem Hero.
   Logos deutlich größer, optisch ausgeglichen statt gleich breit, Lauf von
   rechts nach links, Pause bei Hover.
   ══════════════════════════════════════════════════════════════════════════ */
/* f2 (AJ): oben und unten war optisch ungleich, weil das Label zusaetzlich
   Abstand nach unten bringt. Unten deshalb ohne Polster — die Logos sitzen
   direkt auf der Kante zum naechsten Abschnitt. */
/* f3 (AJ, dritte Nennung) · Zweiter Anlauf, und diesmal der richtige.
   Beim ersten Versuch habe ich die LOGOS mathematisch zentriert: das Label
   wanderte aus dem Fluss nach oben, oben und unten standen exakt 66 px.
   Rechnerisch mittig, optisch falsch — nachgemessen am Ergebnis:
   Oberkante bis Label 42, Label bis Logos 45, Logos bis Unterkante 87.
   Der untere Weissraum war doppelt so gross wie der obere, weil das absolut
   liegende Label fuer die Rechnung nicht zaehlte, fuer das Auge aber sehr wohl.
   Sichtbar ist die GRUPPE aus Label und Logos, und die gehoert mittig.
   Das Label steht deshalb wieder im Fluss, und das Band traegt oben wie unten
   denselben Abstand. Damit ist die Gruppe automatisch ausgewogen, egal wie
   lang das Label wird oder ob es umbricht.
   f4 (AJ) · Unter dem Band standen 160 px bis zum Brand Toolkit, zwischen
   Brand Toolkit und Instant Share dagegen 320. --beat ist derselbe Takt und
   faellt an den Haltepunkten mit. */
.brands{
  border-block:var(--b-inner) solid var(--ink);
  background:var(--paper); padding-block:var(--sp-5); overflow:hidden;
  margin-bottom:var(--beat);
}
.brands .lbl{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--ink-3);
  padding-inline:var(--edge-pad); margin-bottom:var(--sp-4);
}
.marquee{ overflow:hidden; position:relative; }
.marquee-track{
  display:flex; align-items:center; gap:var(--sp-8); width:max-content;
  animation:marq 40s linear infinite;
}
.marquee:hover .marquee-track{ animation-play-state:paused; }
@keyframes marq{ from{ transform:translateX(0) } to{ transform:translateX(-50%) } }
/* Optischer Ausgleich: Höhe führt, Breite folgt. GON ist fast quadratisch und
   würde bei gleicher Breite viermal so groß wirken. */
/* F2: alle Zeichen etwa GLEICH GROSS. Gleiche Flaeche waere falsch — dann
   wird eine breite Wortmarke winzig (genau Stefans Kritik an MOMMY I'M SORRY).
   Loesung: gleiche BOX fuer alle, jedes Zeichen skaliert per contain hinein.
   Damit belegt jede Marke denselben optischen Platz. */
.marquee-track img{
  width:200px; height:84px; flex:none;
  object-fit:contain; object-position:center;
}
/* f2 (AJ) · Das Band setzte einmal pro Runde sichtbar zurueck. Die Animation
   faehrt auf -50 % der Spurbreite, das trifft die Satzbreite aber nur, wenn
   beide Haelften EXAKT gleich breit sind. Gemessen: 8 Bilder à 200 px und
   7 Luecken à 96 px ergeben 2272 px, die Haelfte ist 1136 — ein Satz misst
   mit seiner nachlaufenden Luecke aber 1184. Jede Runde sprang das Band um
   48 px zurueck.
   Die Luecke wandert deshalb vom Container in den Satz: gap plus ein
   nachlaufendes padding-right. Dann ist ein Satz exakt die halbe Spur und
   -50 % landet punktgenau auf dem Anfang der Kopie.
   Der Container verliert seinen gap nur, wenn die Saetze wirklich gebaut
   wurden. Bei reduzierter Bewegung laeuft das Skript nicht, dort bleiben die
   Bilder direkte Kinder und brauchen ihn weiter. */
.marquee-track.mq-loop{ gap:0; }
.mq-set{ display:flex; align-items:center; gap:var(--sp-8); padding-right:var(--sp-8); }

@media (max-width:767px){
  .marquee-track{ gap:var(--sp-6) }
  .mq-set{ gap:var(--sp-6); padding-right:var(--sp-6) }
  .marquee-track img{ width:132px; height:56px }
}
@media (prefers-reduced-motion: reduce){
  .marquee-track{ animation:none; width:100%; justify-content:space-around; flex-wrap:wrap }
}

/* ══════════════════════════════════════════════════════════════════════════
   Safe-Zones-Demo (R1.8 / R2.5 / F11) — abstrakt, kein echter Post.
   Der Formatwechsel 4:5 ↔ 9:16 ist EINE durchgehende, kraeftig ein- und
   ausgeleitete Bewegung. aspect-ratio ist nicht zuverlaessig animierbar,
   darum fuehrt die HOEHE des Rahmens den Morph — optisch dasselbe, aber weich.
   ══════════════════════════════════════════════════════════════════════════ */
.szdemo{ position:relative; }
.szdemo .frame{
  position:relative; margin-inline:auto; width:min(300px, 78%);
  height:375px;                       /* 4:5 bei 300 Breite */
  transition:height var(--t-web-morph), width var(--t-web-morph);
}
.szdemo[data-active="916"] .frame{
  width:min(232px, 62%); height:412px;   /* 9:16, gleiche optische Masse */
}
/* Der Meta-Post fuellt den Rahmen und wandert mit */
.szdemo .frame .mpost{
  position:absolute; inset:0; aspect-ratio:auto; width:100%; height:100%;
  transition:padding var(--t-web-morph);
}
/* Im Hochformat mehr Luft und die Bildflaeche waechst */
.szdemo[data-active="916"] .frame .mpost{ padding:7% }
.szdemo .frame .mp-img{ transition:flex-basis var(--t-web-morph), border-radius var(--t-web-morph) }
.szdemo[data-active="916"] .frame .mp-img{ border-radius:0 100% 0 0 }

/* Die sicheren Zonen — gestrichelt, weil sie nie mitexportiert werden */
/* F3 (AJ): die sicheren Zonen sind das Feature dieses Abschnitts — sie hinter
   Hover zu verstecken war der eigentliche Fehler. Jetzt immer sichtbar, Hover
   verstaerkt nur noch. z-index ueber der Bildflaeche, damit die Form sie nie
   verdeckt. */
/* neu-f6 (AJ) · Der Hinweis sagt „zum Anzeigen darüberfahren", die Zonen
   standen aber schon im Ruhezustand bei 0.72 offen. Hovern hob sie lediglich
   auf 1 — ein Unterschied, den niemand sieht. Es gab also nichts anzuzeigen,
   und der Hinweis war eine Behauptung. Ruhe ist jetzt 0, Hover zeigt wirklich. */
.szdemo .zone{
  position:absolute; inset:9%; z-index:8; pointer-events:none;
  border:1.5px dashed var(--loud);
  opacity:0; transition:opacity var(--t-state), inset var(--t-web-morph);
}
.szdemo[data-active="916"] .zone{ inset:7% 9%; }
/* Das Label sass auf -20px und wurde von der Bildform ueberdeckt. Jetzt sitzt
   es INNEN auf einer eigenen Flaeche — auf Orange wie auf Weiss lesbar. */
.szdemo .zone::after{
  content:attr(data-lbl); position:absolute; left:-1.5px; top:-1.5px;
  font-family:var(--font-mono); font-size:9.5px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--paper); background:var(--loud);
  padding:3px 7px; white-space:nowrap;
}
.szdemo:hover .zone, .szdemo.show .zone, .szdemo:focus-within .zone{ opacity:1; }
/* M14 · Ohne Hover gibt es nichts aufzudecken — auf Touch stehen die Zonen
   dauerhaft. Das ist dort die ehrlichere Darstellung: der Beweis liegt
   offen, statt hinter einer Geste, die das Geraet nicht kennt. */
@media (hover:none),(pointer:coarse){ .szdemo .zone{ opacity:1; } }
/* Die Bildform darf im 9:16 nicht in die Textzeilen laufen (AJ). */
.szdemo[data-active="916"] .frame .mp-img{ border-radius:0 100% 0 0; flex-basis:64% !important; }
.szdemo .frame .mp-lines{ position:relative; z-index:6; }

.szdemo .seg{ display:flex; gap:6px; justify-content:center; margin-top:var(--sp-4); }
.szdemo .hint{
  text-align:center; margin-top:12px; font-family:var(--font-mono);
  font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--ink-3);
}
@media (prefers-reduced-motion: reduce){
  .szdemo .frame, .szdemo .zone, .szdemo .frame .mpost{ transition:none }
}

/* ══════════════════════════════════════════════════════════════════════════
   „Für wen" mit Hintergrundvideo (R2.4) — 21:9, randlos, emotional.
   Statt sechs Panels: das Video holt ab, die Zielgruppen laufen als eine
   ruhige Mono-Zeile darunter.
   ══════════════════════════════════════════════════════════════════════════ */
/* M02 · aspect-ratio zusammen mit min-height laesst den Browser die BREITE
   aus der Hoehe ableiten, sobald die Mindesthoehe greift: bei 834 px Fenster
   sind 420 x 21/9 genau 980 px. Die Startseite war dadurch auf dem Tablet
   146 px breiter als das Fenster und scrollte seitlich — als einzige der
   sechzehn Seiten. width:100% klemmt die Breite ans Fenster, die Mindesthoehe
   macht den Abschnitt dann nur hoeher statt breiter. Verwandt mit der
   Safari-Falle im HANDOVER: bei aspect-ratio immer die eine Achse festnageln. */
.whofor{
  position:relative; overflow:hidden;
  width:100%; aspect-ratio:21/9; min-height:420px;
  display:flex; align-items:center;
  background:var(--ink);
}
.whofor video, .whofor img.poster{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; z-index:0;
}
/* Scrim: das Video darf die Schrift nie schlucken. Ink von links, damit
   linksbündiger Text sicher über 4,5:1 bleibt. */
.whofor::after{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(90deg, rgba(17,17,16,.88) 0%, rgba(17,17,16,.72) 46%, rgba(17,17,16,.30) 100%);
}
.whofor .inner{ position:relative; z-index:2; color:var(--paper); }
.whofor .kicker{ color:var(--loud); }
.whofor h2{ max-width:26ch; }
.whofor p{ color:rgba(255,255,255,.86); }
/* Zielgruppen als Zeile, nicht als Kacheln */
.whofor .groups{
  display:flex; flex-wrap:wrap; gap:10px 0; align-items:center;
  margin-top:var(--sp-5);
  font-family:var(--font-mono); font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; color:rgba(255,255,255,.72);
}
.whofor .groups span:not(:last-child)::after{
  content:'·'; margin:0 12px; color:var(--loud);
}
.whofor .groups .free{ color:var(--loud); }
@media (max-width:767px){
  .whofor{ aspect-ratio:auto; min-height:0; padding-block:var(--sp-8); }
  .whofor::after{ background:linear-gradient(180deg, rgba(17,17,16,.84), rgba(17,17,16,.70)); }
}

/* Pre-Footer (R1.10) — Orange, schwarze Textur, Founder-Wort */
.band{ position:relative; overflow:hidden; }
/* :not(.tilefield) ist Pflicht — sonst überschreibt diese Regel das
   position:absolute des Kachelfelds, es fällt in den Fluss, bekommt Höhe 0
   und wird nie gefüllt. */
.band > *:not(.tilefield){ position:relative; z-index:2; }
.band .tilefield{ z-index:1; }
/* Founder-Wort auf eigener Ink-Fläche. Grund: Farbgesetz 2 erlaubt auf
   Akzentflächen nur reines Weiß ab 24 px — ein 19-px-Zitat und eine 11-px-
   Mono-Zeile direkt auf Orange wären zu schwach (3,4:1). Auf Ink sind es
   19:1, und die Textur bleibt drumherum sichtbar. */
/* Weiße Karte statt Ink: eine Ink-Fläche würde mit der schwarzen Textur zu
   einem formlosen Fleck verschmelzen. Weiß trennt, und Ink-auf-Weiß sind
   19:1 — damit ist auch Farbgesetz 2 erfüllt (kein Kleintext auf Orange). */
.founder{
  margin-top:var(--sp-7); padding:var(--sp-5) var(--sp-6);
  background:var(--paper); color:var(--ink);
  border-radius:var(--r-panel); max-width:74ch;
}
.founder p{ font-size:20px; line-height:1.55; margin:0; }
.founder .who{
  display:inline-block; margin-top:var(--sp-3);
  font-family:var(--font-mono); font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--acc-800);
}

/* Parallaxebenen — Faktoren werden in motion.js gesetzt (§10) */
[data-par]{ will-change:transform; }

/* ══════════════════════════════════════════════════════════════════════════
   DOKUMENTVORLAGE (C2) — Impressum, Datenschutz, AGB, Widerruf, Kündigung,
   FAQ, Download. Eine Spalte, Randnavigation, max. 68 Zeichen Zeilenlänge.
   Rechtstexte müssen lesbar sein, nicht dekorativ — hier macht die Typografie
   die ganze Arbeit. Kein Fließtext in Orange, nur Links.
   ══════════════════════════════════════════════════════════════════════════ */
.docwrap{ display:grid; grid-template-columns:220px minmax(0,1fr); gap:var(--sp-7); align-items:start; }
@media (max-width:1023px){ .docwrap{ grid-template-columns:1fr; gap:var(--sp-5); } }

/* V24 · Inhaltsverzeichnis fuer die langen Dokumente. AGB und Datenschutz sind
   am Handy je rund 8.500 Bildpunkte lang, ohne Sprungmarken und ohne Weg nach
   oben. Niemand liest sie von vorn bis hinten — man sucht eine Sache: wo
   liegen meine Daten, wie komme ich raus, was kostet es. Am Schreibtisch endet
   die Textspalte gleichzeitig bei zwei Dritteln, das rechte Drittel lag leer.
   Ein Bauteil loest beides. */
.docwrap.has-toc{ grid-template-columns:220px minmax(0,1fr) 210px; }
@media (max-width:1279px){ .docwrap.has-toc{ grid-template-columns:220px minmax(0,1fr); } }
@media (max-width:1023px){ .docwrap.has-toc{ grid-template-columns:1fr; } }

.doctoc{ position:sticky; top:96px; }
.doctoc-h{
  font-family:var(--font-mono); font-size:10px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3); margin:0 0 14px; font-weight:400;
}
.doctoc a{
  display:block; border:0; color:var(--ink-2); font-size:13px; line-height:1.4;
  padding:6px 0 6px 12px; border-left:2px solid var(--hair);
}
.doctoc a:hover{ color:var(--ink); border-left-color:var(--ink); }
.doctoc a.aktiv{ color:var(--ink); border-left-color:var(--loud); }
/* Bis 1279 px wandert es unter die Randnavigation, am Handy klappt es zu. */
@media (max-width:1279px){
  .doctoc{ position:static; grid-column:1; grid-row:2; margin-top:var(--sp-4); }
}
@media (max-width:1023px){
  .doctoc{ margin-top:0; border-top:1px solid var(--hair); padding-top:var(--sp-3); }
  .doctoc details > summary{
    cursor:pointer; font-family:var(--font-mono); font-size:10px; letter-spacing:.14em;
    text-transform:uppercase; color:var(--ink-3); padding:8px 0; list-style:none;
  }
  .doctoc details > summary::-webkit-details-marker{ display:none; }
  .doctoc details > summary::after{ content:' +'; }
  .doctoc details[open] > summary::after{ content:' −'; }
}
/* Sprungziele nicht unter die klebende Kopfleiste rutschen lassen */
.doc h2[id]{ scroll-margin-top:96px; }

/* Randnavigation — bleibt beim Scrollen stehen */
.docnav{ position:sticky; top:96px; }
/* T15 · wie im Fuss: Ebene und Aussehen getrennt. Die Bereichsueberschrift
   der Seitenleiste war h6 neben einer h1 im Inhalt. */
.docnav h6, .docnav .docnav-h{
  font-family:var(--font-mono); font-size:10px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3); margin:0 0 14px; font-weight:400;
}
.docnav a{
  display:block; border:0; padding:9px 0 9px 14px; font-size:14px;
  color:var(--ink-2); border-left:var(--b-inner) solid transparent;
}
.docnav a:hover{ color:var(--ink); }
.docnav a[aria-current="page"]{
  color:var(--ink); font-weight:600; border-left-color:var(--loud);
}
@media (max-width:1023px){
  .docnav{ position:static; }
  .docnav div{ display:flex; flex-wrap:wrap; gap:4px; }
  .docnav a{ padding:8px 12px; border-left:0; background:var(--bone); }
  .docnav a[aria-current="page"]{ background:var(--ink); color:var(--paper); }
}

/* Satzspiegel */
.doc{ max-width:68ch; }
.doc h1{
  font-size:clamp(34px,4.2vw,52px); line-height:1.0; letter-spacing:-.032em;
  margin:0 0 12px;
}
.doc .upd{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--ink-3);
  padding-bottom:var(--sp-4); border-bottom:var(--b-hair) solid var(--hair);
}
.doc h2{
  font-size:19px; line-height:1.3; letter-spacing:-.01em;
  margin:var(--sp-6) 0 0;
}
.doc h3{ font-size:16px; margin:var(--sp-5) 0 0; }
.doc p, .doc li{ font-size:17px; line-height:1.7; color:#3F3A33; }
.doc p{ margin:12px 0 0; }
.doc ul, .doc ol{ margin:12px 0 0; padding-left:22px; }
.doc li{ margin:6px 0 0; }
/* V03 · Stand als .doc a und schlug damit .pill-loud, weil ein Klassen-plus-
   Typselektor spezifischer ist. Ergebnis: der Knopf "Editor oeffnen" auf der
   Download-Seite war orange auf orange, gemessene 1,58:1 — der schlechteste
   Wert im ganzen Projekt. Knoepfe sind jetzt ausgenommen.
   T13 · --acc-700 erreichte auf --bone nur 4,49:1. --acc-800 haelt 5,0:1. */
.doc a:not(.pill){ color:var(--acc-800); }

/* neu-f8 · Eintragefeld auf /download. Zwei Elemente in einer Zeile, am Handy
   untereinander. Kein Kasten, keine Kachel — die Seite ist ein Dokument. */
.nl{ margin-top:var(--sp-5); max-width:52ch; }
.nl > label{
  display:block; font-family:var(--font-mono); font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3); margin-bottom:10px;
}
.nl-row{ display:flex; gap:10px; align-items:stretch; }
.nl-row .input{ flex:1 1 auto; min-width:0; }
.nl-row .pill{ flex:0 0 auto; }
@media (max-width:560px){ .nl-row{ flex-direction:column; } }
.nl-msg{ margin:12px 0 0; font-size:14px; min-height:1.4em; }
.nl-msg.ok{ color:var(--ok); font-weight:600; }
.nl-msg.err{ color:var(--danger); font-weight:600; }
.nl-fein{ margin:10px 0 0; font-size:12.5px; line-height:1.5; color:var(--ink-3); }

/* V12 · Das Muster-Widerrufsformular bildete seine Ausfuellzeilen mit langen
   Unterstrichketten ab. Die brechen nicht um und machten die Seite am Handy
   407 statt 390 Pixel breit — Seitwaertsscrollen ausgerechnet auf dem
   Dokument, das Sorgfalt beweisen soll. Jetzt eine echte Linie, die sich der
   Breite anpasst. Der Wortlaut der Musterbelehrung bleibt unberuehrt. */
.doc .blank{
  display:inline-block; vertical-align:baseline;
  min-width:120px; max-width:100%; width:14em;
  border-bottom:1px solid var(--ink); margin-bottom:2px;
}
.doc p{ overflow-wrap:anywhere; }
.doc table{ width:100%; border-collapse:collapse; margin-top:var(--sp-4); font-size:15px; }
.doc th, .doc td{ text-align:left; padding:10px 12px; border-bottom:var(--b-hair) solid var(--hair); }
.doc th{ font-family:var(--font-mono); font-size:11px; letter-spacing:.12em; text-transform:uppercase; color:var(--ink-3); font-weight:400; }
.doc hr{ border:0; border-top:var(--b-hair) solid var(--hair); margin:var(--sp-5) 0; }

/* FAQ-Aufklappzeilen: Haarlinie, Plus/Minus rechts, immer nur eine offen */
.qa{ border-bottom:var(--b-hair) solid var(--hair); }
.qa > button{
  width:100%; display:flex; align-items:center; gap:var(--sp-3);
  background:none; border:0; cursor:pointer; text-align:left;
  padding:var(--sp-3) 0; min-height:var(--touch);
  font-family:var(--font-display); font-weight:600; font-size:17px; color:var(--ink);
}
.qa > button::after{
  content:'+'; margin-left:auto; flex:none;
  font-family:var(--font-mono); font-size:18px; color:var(--loud);
  transition:transform var(--t-state);
}
.qa > button[aria-expanded="true"]::after{ content:'–'; }
.qa .a{
  overflow:hidden; max-height:0;
  transition:max-height var(--t-web-morph);
}
.qa .a > div{ padding:0 0 var(--sp-4); }
.qa .a p{ font-size:16px; line-height:1.65; color:var(--ink-2); margin:0 0 10px; }

/* Kündigungsformular (§ 312k) — nutzt die PLAKAT-Bausteine.
   Das Formular selbst und sein Script bleiben unverändert; nur die Hülle. */
.cf{ display:grid; gap:var(--sp-4); margin-top:var(--sp-5); max-width:52ch; }
.cf label{
  display:block; font-family:var(--font-mono); font-size:11px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--ink-3);
  margin-bottom:8px;
}
.cf input, .cf textarea{
  width:100%; min-height:var(--touch); padding:12px 14px;
  font-family:var(--font-display); font-size:16px; color:var(--ink);
  background:var(--bone); border:var(--b-hair) solid transparent;
  border-radius:var(--r-content); caret-color:var(--loud);
}
.cf textarea{ min-height:104px; resize:vertical; }
.cf input:focus-visible, .cf textarea:focus-visible{
  background:var(--paper); border:1.5px solid var(--loud); outline:none;
}
.cf-msg{ font-size:15px; color:var(--ink-2); min-height:1.2em; }
.cf-msg.ok{ color:var(--ok); } .cf-msg.err{ color:var(--danger); }
.cf .pill{ justify-self:start; }

/* Galerie-Kachelraster (C2/F14) — Masonry über columns, Radius 0 (Inhalt) */
.galgrid{ columns:4; column-gap:var(--gutter); }
@media (max-width:1023px){ .galgrid{ columns:2 } }
@media (max-width:600px){ .galgrid{ columns:1 } }
.galcard{
  display:block; border:0; break-inside:avoid;
  margin-bottom:var(--gutter); position:relative;
  background:var(--ink); overflow:hidden;
}
.galcard .galimg{
  display:block; width:100%; aspect-ratio:4/5;
  background-size:cover; background-position:center;
  transition:transform var(--t-web-morph);
}
.galcard.t1 .galimg{ aspect-ratio:4/5 }
.galcard.t2 .galimg{ aspect-ratio:1/1 }
.galcard.t3 .galimg{ aspect-ratio:9/16 }
.galcard.t4 .galimg{ aspect-ratio:3/4 }
.galcard:hover .galimg{ transform:scale(1.03); }
.galcard .galmeta{
  position:absolute; inset:auto 0 0 0; padding:var(--sp-4);
  background:linear-gradient(180deg, rgba(17,17,16,0), rgba(17,17,16,.78));
  color:var(--paper);
}
.galcard .galk{
  display:block; font-family:var(--font-mono); font-size:10px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--loud);
}
.galcard .galh{
  display:block; font-family:var(--font-display); font-weight:700;
  font-size:19px; line-height:1.1; letter-spacing:-.02em; margin-top:6px;
}

/* Rechtslinks im Fuß von konto/projects (Redline: von jeder Seite erreichbar,
   auch eingeloggt). Die Seiten tragen eigenes CSS — daher eigene Klasse. */
.lawlinks{ display:flex; flex-wrap:wrap; gap:16px; }
.lawlinks a{
  font-size:13px; color:var(--ink-3, #6E6862); text-decoration:none;
  border-bottom:1px solid transparent;
}
.lawlinks a:hover{ color:var(--ink, #111110); border-bottom-color:currentColor; }


/* ══════════════════════════════════════════════════════════════════════════
   F2 · Instant Share als Bild (AJ): Post poppt auf → faehrt in ein Telefon →
   zwei weitere docken nacheinander an. Kein echter Link, kein Rechteck-Flug.
   Ein Takt von 11 s, --e-heavy wie die ganze Website.
   ══════════════════════════════════════════════════════════════════════════ */
.shflow{ position:relative; aspect-ratio:1/1; display:flex; align-items:center; justify-content:center; }
.sf-phone{
  /* Hoehe zuerst, Breite aus dem Verhaeltnis: so bleibt die Groesse auch in
     Safari definiert (aspect-ratio allein auf absoluten Elementen ist dort
     unzuverlaessig). */
  position:absolute; height:86%; aspect-ratio:9/17.5; width:auto;
  background:var(--paper); border:2px solid var(--ink); border-radius:22px;
  padding:7px 6px; box-sizing:border-box;
}
.sf-phone::before{                       /* Kameraleiste, ein Strich statt Deko */
  content:''; position:absolute; top:7px; left:50%; transform:translateX(-50%);
  width:22%; height:3px; border-radius:999px; background:var(--ink);
}
.sf-scr{ width:100%; height:100%; overflow:hidden; border-radius:15px; background:var(--bone); }
.sf-scr .mpost{ width:100%; height:100%; border:0; }

/* Telefon 1 traegt den Post: erst ist nur der Post da (Rahmen unsichtbar),
   dann faehrt der Rahmen auf. */
/* F2 (AJ): 20 % schneller — 11 s auf 8,8 s. */
.sf-p1{ z-index:3; animation:sfP1 8.8s var(--e-heavy) infinite; }
.sf-p2{ z-index:2; animation:sfP2 8.8s var(--e-heavy) infinite; }
.sf-p3{ z-index:1; animation:sfP3 8.8s var(--e-heavy) infinite; }

@keyframes sfP1{
  0%,4%    { opacity:0; transform:scale(.82) translateY(14px); border-color:transparent; border-radius:8px; }
  14%,26%  { opacity:1; transform:scale(1.06) translateY(0);   border-color:transparent; border-radius:8px; }
  36%,92%  { opacity:1; transform:scale(1) translateY(0);      border-color:var(--ink);  border-radius:22px; }
  100%     { opacity:0; transform:scale(.82) translateY(14px); border-color:transparent; border-radius:8px; }
}
@keyframes sfP2{
  0%,44%   { opacity:0; transform:translateX(0) scale(.9); }
  56%,92%  { opacity:1; transform:translateX(62%) scale(.88); }
  100%     { opacity:0; transform:translateX(0) scale(.9); }
}
/* f6 (AJ) · Der Faecher oeffnete einseitig. sfP2 wurde bei 56 % sichtbar,
   sfP3 erst bei 74 % — dazwischen lagen 18 Prozent der Laufzeit, also rund
   1,6 Sekunden, in denen NUR die rechte Karte stand. In dem Fenster wirkt die
   Gruppe rechtslastig, obwohl die Ruhelage exakt mittig sitzt (nachgemessen:
   144 px Rand links wie rechts, 40 px oben wie unten). Beide Karten fahren
   jetzt gleichzeitig aus, der Faecher oeffnet symmetrisch, und die Mitte
   haelt zu jedem Zeitpunkt der Animation. */
@keyframes sfP3{
  0%,44%   { opacity:0; transform:translateX(0) scale(.9); }
  56%,92%  { opacity:1; transform:translateX(-62%) scale(.88); }
  100%     { opacity:0; transform:translateX(0) scale(.9); }
}
@media (max-width:767px){ .sf-phone{ height:78%; } }
@media (prefers-reduced-motion:reduce){
  .sf-p1,.sf-p2,.sf-p3{ animation:none; opacity:1; }
  .sf-p2{ transform:translateX(62%) scale(.88); }
  .sf-p3{ transform:translateX(-62%) scale(.88); }
}
