Zum Inhalt
← Mikroanimationen

Eckenformen mit corner-shape (Squircle, Scoop, Notch, Bevel)

Squircle, Scoop, Notch und Bevel als echte Eckenformen: Ticket, Tags, Avatar und Button bekommen eine eigene Eckensprache, die beim Umschalten weich morpht.

Design-Systeme, Kurse, Apps, Tickets: jede Komponente bekommt eine eigene Eckenform (squircle, bevel, notch, scoop), border-radius bleibt der Rückfall. Unterumschalter: Eckensprache, Alles Squircle, Nur Rundung.

border-radius legt die Größe der Ecke fest, corner-shape ihre Form. Mögliche Werte: round (Standard), squircle (Superellipse, wie App-Icons), bevel (abgeschrägt), scoop (nach innen gewölbt), notch (eckige Kerbe), square und stufenlos superellipse(k). Jede Ecke lässt sich einzeln setzen, etwa corner-shape: bevel round round bevel. Hintergrund, Rahmen, Schatten, outline und overflow folgen der Form. Das unterscheidet corner-shape von clip-path. Browserstand laut MDN (31.10.2026): Chrome und Edge ab 139, Safari und Firefox nur in Vorschauversionen.

Ecken geben einer Oberfläche Charakter, ohne SVG-Masken oder clip-path. Squircles wirken weicher und hochwertiger als Kreisradien. Scoop, Notch und Bevel machen aus Tickets, Tags und Buttons erkennbare Objekte. Schatten und Rahmen bleiben dabei korrekt.

Wann einsetzen

Avatare und App-Icons (Squircle), Tickets und Gutscheine (Scoop), Status- und Themen-Tags (Notch, Bevel), Fahnen und Richtungs-Badges, Hover-Morph an Buttons. Gut in Design-Systemen, die neben dem Radius-Token ein Form-Token führen.

Wann nicht

Wenn die Form inhaltlich wichtig ist: Safari und Firefox zeigen nur die normale Rundung. Nicht als Ersatz für freie Silhouetten, dafür shape() oder clip-path nehmen.

Varianten

  • Squircle-Avatar: border-radius: 50 % plus corner-shape: squircle, ohne Unterstützung ein Kreis
  • Logo-Fahne mit gemischten Ecken: border-radius: 16px 0 0 16px; corner-shape: bevel round round bevel (CSS-Tricks)
  • Radius-Tokens nur bei Unterstützung umschalten: @supports (corner-shape: squircle) { :root { --radius-md: 10px } } (utilitybend: 3, 4, 10, 14 px)
  • Ticket oder Gutschein aus zwei Teilen mit scoop-Ecken an der Abrisskante
  • Status-Tags mit notch, Themen-Tags mit bevel
  • Hover-Morph am Button: bevel → squircle per transition
  • Freie Formen mit border-shape (ab Chrome 147) und polygon(round …) (ab Chrome 150): Lernweg als Pfeilkette, Button als Wegweiser, Stern-Sticker, Sprechblase; Rahmen und Schatten folgen der Form, Rückfall clip-path

Umsetzung

Zuerst das vollständige Design mit border-radius bauen. Dann ergänzen: @supports (corner-shape: squircle) { .avatar { corner-shape: squircle; } }. Squircles wirken kleiner als Kreisradien, deshalb den Radius etwas größer wählen. Pro Ecke: corner-shape: bevel round round bevel. Feinsteuerung mit superellipse(k): 1 ist round, 2 squircle, 0 bevel, -1 scoop. Die Werte interpolieren über ihre superellipse()-Entsprechung, deshalb lässt sich die Form animieren: .btn { border-radius: 18px; corner-shape: bevel; transition: corner-shape .3s cubic-bezier(.37, 0, .63, 1); } .btn:hover { corner-shape: squircle; }. Als Token neben --radius ein --corner führen.

Robust umsetzen

Telefon. Android-Chrome unterstützt corner-shape, iOS-Safari noch nicht. Dort greift die normale Rundung. Die Bedienung ändert sich nicht.

Ohne Bewegung. Der Form-Morph ist dezent. Bei prefers-reduced-motion: reduce trotzdem transition: none setzen, die Form wechselt dann sofort.

Barrierefrei. Rein visuell. Der Fokusring (outline) folgt der Form: Bei scoop und notch prüfen, dass er sichtbar bleibt. Tiefe Kerben dürfen die Klickfläche nicht verkleinern.

Code

<!DOCTYPE html>
<!--
  Eckenformen mit corner-shape (Squircle, Scoop, Notch, Bevel)
  Fundus · Mikroanimationen · https://cecodesign.de/lab/fundus/mikroanimationen/corner-shape-eckenformen/
  Eigenständige Datei. Bilder liegen hier unter bilder/ – eigene einsetzen.
-->
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Eckenformen mit corner-shape · Fundus-Demo</title>
<script>document.documentElement.classList.add('js');if(matchMedia('(prefers-reduced-motion: reduce)').matches)document.documentElement.classList.add('reduziert')</script>
<style>
@font-face { font-family: 'Bricolage Grotesque'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/bricolage-grotesque:vf@latest/latin-opsz-normal.woff2') format('woff2-variations'); font-weight: 200 800; font-display: swap; }
@font-face { font-family: 'Onest'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/onest:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 100 900; font-display: swap; }
@font-face { font-family: 'Shantell Sans'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/shantell-sans:vf@latest/latin-full-normal.woff2') format('woff2-variations'); font-weight: 300 800; font-display: swap; }
@font-face { font-family: 'Geist Mono'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/geist-mono:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 100 900; font-display: swap; }

:root {
  /* Rezept „kurs-coaching-lernweg“: warmer heller Grund, fast schwarze Tinte, ein Markenton (Münster-Sandstein), eigene Erfolgsfarbe */
  --grund: #f5f3f1; --karte: #ffffff; --tinte: #141414; --leise: rgba(20, 20, 20, .6); --linie: rgba(20, 20, 20, .1);
  --marke: #c2412d; --marke-tief: #9e2f1f; --gelb: #f7c325; --rhein: #b8c7f0; --erfolg: #10bf7a; --papier: #fbf6ec;
  /* Gemessen bei zachleat.com: cubic-bezier(.37, 0, .63, 1); Hover-Morph 250–400 ms */
  --kurve: cubic-bezier(0.37, 0, 0.63, 1);
  --d-wechsel: 400ms; --d-hover: 300ms;
}

/* ---------- Formen-Tokens: drei Eckensprachen ----------
   border-radius = Größe der Ecke (gilt überall), corner-shape = Form (nur mit @supports). */
body, [data-ecken="sprache"] {
  --r-karte: 36px;          --f-karte: squircle;
  --r-bild: 32px;           --f-bild: squircle;
  --r-avatar: 50%;          --f-avatar: squircle;
  --r-status: 8px;          --f-status: notch;
  --r-genre: 10px;          --f-genre: bevel;
  --r-modul: 7px;           --f-modul: bevel;
  --r-cta: 18px;            --f-cta: bevel;           --f-cta-hover: squircle;
  --r-ticket: 18px;         --f-ticket: round scoop scoop round;   --f-abriss: scoop round round scoop;
  --r-sticker: 50%;         --f-sticker: superellipse(-0.3);
  --r-fahne: 16px 0 0 16px; --f-fahne: bevel round round bevel;
  --r-knopf: 12px;          --f-knopf: squircle;
}
[data-ecken="squircle"] {
  /* Token-Ansatz wie bei utilitybend: ein Formwert für alles, Radien etwas größer als bei round */
  --r-karte: 44px;          --f-karte: squircle;
  --r-bild: 40px;           --f-bild: squircle;
  --r-avatar: 50%;          --f-avatar: squircle;
  --r-status: 10px;         --f-status: squircle;
  --r-genre: 10px;          --f-genre: squircle;
  --r-modul: 10px;          --f-modul: squircle;
  --r-cta: 18px;            --f-cta: squircle;        --f-cta-hover: squircle;
  --r-ticket: 14px;         --f-ticket: squircle;     --f-abriss: squircle;
  --r-sticker: 50%;         --f-sticker: squircle;
  --r-fahne: 14px;          --f-fahne: squircle;
  --r-knopf: 14px;          --f-knopf: squircle;
}
[data-ecken="rund"] {
  /* Rückfallebene: so sehen es Safari und Firefox (nur border-radius) */
  --r-karte: 28px;          --f-karte: round;
  --r-bild: 24px;           --f-bild: round;
  --r-avatar: 50%;          --f-avatar: round;
  --r-status: 6px;          --f-status: round;
  --r-genre: 6px;           --f-genre: round;
  --r-modul: 5px;           --f-modul: round;
  --r-cta: 14px;            --f-cta: round;           --f-cta-hover: round;
  --r-ticket: 14px;         --f-ticket: round;        --f-abriss: round;
  --r-sticker: 50%;         --f-sticker: round;
  --r-fahne: 10px 0 0 10px; --f-fahne: round;
  --r-knopf: 10px;          --f-knopf: round;
}

/* ---------- Der Effekt ---------- */
.form {
  border-radius: var(--r);
  transition: border-radius var(--d-wechsel) var(--kurve), corner-shape var(--d-wechsel) var(--kurve),
              background-color 150ms var(--kurve), color 150ms var(--kurve);
}
@supports (corner-shape: squircle) {
  .form { corner-shape: var(--f); }
}
.karte   { --r: var(--r-karte);   --f: var(--f-karte); }
.bild    { --r: var(--r-bild);    --f: var(--f-bild); overflow: clip; }
.avatar  { --r: var(--r-avatar);  --f: var(--f-avatar); overflow: clip; }
.status  { --r: var(--r-status);  --f: var(--f-status); }
.genre   { --r: var(--r-genre);   --f: var(--f-genre); }
.modul   { --r: var(--r-modul);   --f: var(--f-modul); }
.cta     { --r: var(--r-cta);     --f: var(--f-cta); }
.ticket  { --r: var(--r-ticket);  --f: var(--f-ticket); }
.abriss  { --r: var(--r-ticket);  --f: var(--f-abriss); }
.sticker { --r: var(--r-sticker); --f: var(--f-sticker); }
.fahne   { --r: var(--r-fahne);   --f: var(--f-fahne); }
.knopf   { --r: var(--r-knopf);   --f: var(--f-knopf); }
/* Hover-Morph am Button: bevel → squircle, 300 ms */
.cta { transition-duration: var(--d-hover); }
.cta:hover, .cta:focus-visible, .cta.zeige { --f: var(--f-cta-hover); background: var(--marke-tief); }

/* ---------- Variante „Freie Formen“: border-shape mit gerundetem polygon() ----------
   border-shape (ab Chrome 147) zeichnet Hintergrund, Rahmen und Schatten entlang einer beliebigen Form,
   polygon(round …) rundet deren Ecken (ab Chrome 150). Lernweg als Pfeilkette, Button als Wegweiser,
   Sticker als Stern, Bildunterschrift als Sprechblase. Ohne Unterstützung: clip-path mit geraden Ecken. */
[data-v="formen"] .lernweg ol { gap: 3px; }
[data-v="formen"] .modul { --spitze: 11px; position: relative; padding: 9px 8px 10px calc(var(--spitze) + 9px); margin-left: calc(var(--spitze) * -1 + 3px); background: #f1e7df; }
[data-v="formen"] .modul:first-child { margin-left: 0; padding-left: 11px; }
[data-v="formen"] .modul.start { background: var(--marke); color: #fff; }
[data-v="formen"] .modul.start b { color: #ffe3c9; }
[data-v="formen"] .cta { --spitze: 14px; padding-right: 40px; border-radius: 0; }
[data-v="formen"] .cta:hover, [data-v="formen"] .cta:focus-visible, [data-v="formen"] .cta.zeige { --spitze: 24px; }
[data-v="formen"] .cta svg { transition: translate var(--d-hover) var(--kurve); }
[data-v="formen"] .cta:is(:hover, :focus-visible, .zeige) svg { translate: 4px 0; }
[data-v="formen"] .sticker { border-radius: 0; width: 146px; }
[data-v="formen"] .bild figcaption { border-radius: 0; padding-bottom: 19px; bottom: 6px; }
/* Rückfall (auch per Umschalter „Rückfall“ sichtbar): clip-path mit geraden Ecken, ohne Rahmen und Schatten */
[data-v="formen"] .modul { clip-path: polygon(0 0, calc(100% - var(--spitze)) 0, 100% 50%, calc(100% - var(--spitze)) 100%, 0 100%, var(--spitze) 50%); }
[data-v="formen"] .modul:first-child { clip-path: polygon(0 0, calc(100% - var(--spitze)) 0, 100% 50%, calc(100% - var(--spitze)) 100%, 0 100%); }
[data-v="formen"] .cta { clip-path: polygon(0 0, calc(100% - var(--spitze)) 0, 100% 50%, calc(100% - var(--spitze)) 100%, 0 100%); transition: clip-path var(--d-hover) var(--kurve), background-color 150ms var(--kurve); }
[data-v="formen"] .sticker { clip-path: polygon(50% 0%, 60.6% 10.4%, 75% 6.7%, 79% 21%, 93.3% 25%, 89.6% 39.4%, 100% 50%, 89.6% 60.6%, 93.3% 75%, 79% 79%, 75% 93.3%, 60.6% 89.6%, 50% 100%, 39.4% 89.6%, 25% 93.3%, 21% 79%, 6.7% 75%, 10.4% 60.6%, 0% 50%, 10.4% 39.4%, 6.7% 25%, 21% 21%, 25% 6.7%, 39.4% 10.4%); }
[data-v="formen"] .bild figcaption { clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), 44px calc(100% - 10px), 26px 100%, 30px calc(100% - 10px), 0 calc(100% - 10px)); }
@supports (border-shape: polygon(round 1px, 0 0, 100% 0, 50% 100%)) {
  body[data-v="formen"]:not([data-technik="rueckfall"]) :is(.modul, .cta, .sticker, figcaption) { clip-path: none; }
  body[data-v="formen"]:not([data-technik="rueckfall"]) .modul {
    border: 1.5px solid rgba(20, 20, 20, .14);
    border-shape: polygon(round 4px, 0 0, calc(100% - var(--spitze)) 0, 100% 50%, calc(100% - var(--spitze)) 100%, 0 100%, var(--spitze) 50%);
  }
  body[data-v="formen"]:not([data-technik="rueckfall"]) .modul:first-child { border-shape: polygon(round 4px, 0 0, calc(100% - var(--spitze)) 0, 100% 50%, calc(100% - var(--spitze)) 100%, 0 100%); }
  body[data-v="formen"]:not([data-technik="rueckfall"]) .modul.start { border-color: var(--marke-tief); }
  body[data-v="formen"]:not([data-technik="rueckfall"]) .cta {
    box-shadow: 0 10px 22px -10px rgba(158, 47, 31, .7);
    border-shape: polygon(round 6px, 0 0, calc(100% - var(--spitze)) 0, 100% 50%, calc(100% - var(--spitze)) 100%, 0 100%);
    transition: border-shape var(--d-hover) var(--kurve), background-color 150ms var(--kurve);
  }
  body[data-v="formen"]:not([data-technik="rueckfall"]) .sticker {
    border: 2px solid var(--tinte); box-shadow: 0 6px 0 var(--tinte);
    border-shape: polygon(round 5px, 50% 0%, 60.6% 10.4%, 75% 6.7%, 79% 21%, 93.3% 25%, 89.6% 39.4%, 100% 50%, 89.6% 60.6%, 93.3% 75%, 79% 79%, 75% 93.3%, 60.6% 89.6%, 50% 100%, 39.4% 89.6%, 25% 93.3%, 21% 79%, 6.7% 75%, 10.4% 60.6%, 0% 50%, 10.4% 39.4%, 6.7% 25%, 21% 21%, 25% 6.7%, 39.4% 10.4%);
    transition: border-shape var(--d-hover) var(--kurve), rotate var(--d-hover) var(--kurve);
  }
  body[data-v="formen"]:not([data-technik="rueckfall"]) .sticker:is(:hover, .zeige) {
    rotate: -2deg;
    border-shape: polygon(round 5px, 50% 0%, 59.1% 16.2%, 75% 6.7%, 74.7% 25.3%, 93.3% 25%, 83.8% 40.9%, 100% 50%, 83.8% 59.1%, 93.3% 75%, 74.7% 74.7%, 75% 93.3%, 59.1% 83.8%, 50% 100%, 40.9% 83.8%, 25% 93.3%, 25.3% 74.7%, 6.7% 75%, 16.2% 59.1%, 0% 50%, 16.2% 40.9%, 6.7% 25%, 25.3% 25.3%, 25% 6.7%, 40.9% 16.2%);
  }
  body[data-v="formen"]:not([data-technik="rueckfall"]) .bild figcaption {
    background: #fffdf8; border: 1.5px solid rgba(20, 20, 20, .5); box-shadow: 0 8px 18px -8px rgba(20, 20, 20, .35);
    border-shape: polygon(round 10px, 0 0, 100% 0, 100% calc(100% - 10px), 44px calc(100% - 10px), 26px 100%, 30px calc(100% - 10px), 0 calc(100% - 10px));
  }
}

/* ---------- Grundlagen ---------- */
* { box-sizing: border-box; margin: 0; }
html { background: var(--grund); color: var(--tinte); font-family: 'Onest', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
body { min-height: 100svh; display: grid; grid-template-rows: auto 1fr auto; background: var(--grund); }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
a { color: inherit; }
.mono { font: 500 11px/1.35 'Geist Mono', ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; color: var(--leise); }
.hand { font: 500 15px/1.3 'Shantell Sans', 'Comic Neue', sans-serif; font-variation-settings: 'INFM' 45, 'BNCE' 0; }
:focus-visible { outline: 2px solid var(--marke); outline-offset: 3px; }

/* ---------- Kopf ---------- */
.kopf { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 18px clamp(16px, 4vw, 48px); }
.wortmarke { display: inline-flex; align-items: center; gap: 0; text-decoration: none; font: 750 21px/1 'Bricolage Grotesque', sans-serif; font-variation-settings: 'opsz' 28; letter-spacing: -.03em; }
.wortmarke .fahne { margin-left: 8px; padding: 6px 10px 6px 14px; background: var(--marke); color: #fff; font: 600 13px/1 'Onest', sans-serif; letter-spacing: .01em; }
.nav { display: flex; gap: clamp(14px, 2.4vw, 32px); font-size: 15px; font-weight: 500; }
.nav a { text-decoration: none; color: var(--leise); }
.nav a[aria-current] { color: var(--tinte); }
.kopf .knopf { text-decoration: none; padding: 10px 16px; background: var(--tinte); color: #fff; font-size: 14px; font-weight: 600; }

/* ---------- Bühne ---------- */
.buehne {
  width: min(1200px, 100%); margin: 0 auto; padding: clamp(4px, 1.2vw, 16px) clamp(16px, 4vw, 48px);
  display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: clamp(14px, 2vw, 24px); align-items: stretch;
}
.kurs.karte { background: var(--karte); padding: clamp(24px, 3vw, 44px); display: flex; flex-direction: column; gap: 18px; box-shadow: 0 1px 0 var(--linie), 0 30px 60px -40px rgba(20, 20, 20, .25); }
.kurs .hand { color: var(--marke); }
.kurs h1 {
  font: 700 clamp(2.25rem, 1rem + 3vw, 3.75rem)/1.02 'Bricolage Grotesque', sans-serif; font-variation-settings: 'opsz' 96;
  letter-spacing: -.035em; text-wrap: balance; max-width: 15ch;
}
.kurs h1 em { font-style: normal; position: relative; white-space: nowrap; }
.kurs h1 em::after { content: ''; position: absolute; left: -.04em; right: -.06em; bottom: .06em; height: .22em; background: var(--gelb); z-index: -1; border-radius: 3px; }
.kurs h1 { position: relative; z-index: 0; }
.lead { font-size: 1.0625rem; line-height: 1.6; color: rgba(20, 20, 20, .74); max-width: 46ch; text-wrap: pretty; }
.tags { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; padding: 0; }
.status, .genre { display: inline-flex; align-items: center; gap: 6px; padding: 7px 13px; font-size: 13.5px; font-weight: 600; }
.status { background: var(--tinte); color: #fff; }
.status.gelb { background: var(--gelb); color: var(--tinte); }
.genre { background: #f1ece6; color: var(--tinte); }

.lernweg { display: grid; gap: 10px; }
.lernweg ol { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; }
.modul { display: grid; gap: 3px; padding: 9px 10px 10px; background: #f6f2ee; font-size: 12.5px; line-height: 1.2; font-weight: 500; }
.modul b { font: 600 11px/1 'Shantell Sans', sans-serif; font-variation-settings: 'INFM' 45; color: var(--marke); }

.fuss { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding-top: 18px; border-top: 1px solid var(--linie); }
.person { display: flex; align-items: center; gap: 12px; }
.avatar { width: 54px; height: 54px; flex: none; background: var(--gelb); display: block; }
.avatar svg { display: block; width: 100%; height: 100%; }
.person p { font-size: 14px; line-height: 1.35; color: var(--leise); }
.person strong { display: block; color: var(--tinte); font-weight: 600; font-size: 15px; }
.preis { display: flex; align-items: center; gap: 16px; }
.preis p { text-align: right; font-size: 13px; color: var(--leise); line-height: 1.3; font-variant-numeric: tabular-nums; }
.preis p strong { display: block; font: 700 24px/1.05 'Bricolage Grotesque', sans-serif; font-variation-settings: 'opsz' 32; letter-spacing: -.02em; color: var(--tinte); }
.cta { display: inline-flex; align-items: center; gap: 10px; padding: 15px 22px; background: var(--marke); color: #fff; font-weight: 600; font-size: 15.5px; text-decoration: none; white-space: nowrap; }
.cta svg { width: 16px; height: 16px; }

.seite { display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: clamp(14px, 2vw, 24px); min-width: 0; }
.bild { position: relative; background: var(--papier); min-height: 260px; }
.bild svg.zeichnung { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.bild figcaption { position: absolute; left: 16px; right: 16px; bottom: 16px; width: fit-content; max-width: calc(100% - 32px); padding: 7px 12px; border-radius: 10px; background: rgba(251, 246, 236, .9); color: rgba(20, 20, 20, .78); font-size: 13.5px; }
.sticker {
  position: absolute; right: 18px; top: 18px; width: 132px; aspect-ratio: 1; display: grid; place-content: center; text-align: center;
  background: var(--gelb); color: var(--tinte); rotate: -8deg;
  font: 700 13px/1.1 'Bricolage Grotesque', sans-serif; font-variation-settings: 'opsz' 18; letter-spacing: -.01em;
}
.sticker span { display: block; font: 500 12px/1.2 'Onest', sans-serif; margin-top: 3px; }

.billett { display: grid; grid-template-columns: minmax(0, 1fr) auto; filter: drop-shadow(0 18px 24px rgba(20, 20, 20, .09)); }
.ticket, .abriss { background: var(--karte); padding: 20px 22px; }
.ticket { display: grid; gap: 6px; border-right: 2px dashed rgba(20, 20, 20, .16); }
.ticket .hand { color: var(--marke); font-size: 14px; }
.ticket h2 { font: 650 20px/1.15 'Bricolage Grotesque', sans-serif; font-variation-settings: 'opsz' 24; letter-spacing: -.02em; }
.ticket p { font-size: 14px; color: var(--leise); font-variant-numeric: tabular-nums; }
.abriss { display: grid; align-content: center; justify-items: center; gap: 6px; min-width: 112px; text-align: center; }
.abriss .haken { width: 34px; height: 34px; display: grid; place-items: center; background: var(--erfolg); color: #fff; --r: 11px; --f: squircle; }
[data-ecken="rund"] .abriss .haken { --f: round; }
.abriss .haken svg { width: 18px; height: 18px; }
.abriss small { font-size: 12.5px; font-weight: 600; color: #0b8455; }

/* ---------- Leiste: Varianten und Werte ---------- */
.leiste { display: flex; align-items: center; justify-content: space-between; gap: 16px 28px; flex-wrap: wrap; padding: 14px clamp(16px, 4vw, 48px) 20px; width: min(1200px, 100%); margin: 0 auto; }
.umschalter { display: inline-flex; gap: 2px; padding: 3px; border-radius: 99px; background: rgba(20, 20, 20, .05); }
.umschalter button { padding: 8px 13px; border-radius: 99px; font: 500 11px/1 'Geist Mono', ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; color: var(--leise); transition: background-color 150ms var(--kurve), color 150ms var(--kurve); }
.umschalter button[aria-pressed="true"] { background: var(--karte); color: var(--tinte); box-shadow: 0 1px 2px rgba(20, 20, 20, .12); }
.werte { display: flex; flex-wrap: wrap; gap: 4px 16px; justify-content: flex-end; text-align: right; letter-spacing: .1em; }
.werte span b { color: var(--tinte); font-weight: 500; }
.werte i { font-style: normal; }
.werte .wer b { color: var(--marke); }
.hinweis { display: none; width: 100%; text-align: right; }
.ohne .hinweis { display: block; }
.leiste .gruppe { display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap; }
.umschalter.v button[aria-pressed="true"] { background: var(--tinte); color: #fff; box-shadow: none; }
[data-teil] { display: none !important; }
body[data-v="basis"] [data-teil="basis"], body[data-v="formen"] [data-teil="formen"] { display: inline-flex !important; }
.hinweis-formen { display: none; width: 100%; text-align: right; }
body[data-v="formen"] .ohne-bs .hinweis-formen { display: block; }
body[data-v="formen"] .ohne .hinweis { display: none; }

/* Vorführung: gezeichneter Zeiger */
.zeiger { position: fixed; left: 0; top: 0; z-index: 9; width: 20px; height: 20px; pointer-events: none; display: none; transition: transform 700ms var(--kurve); }
.vorfuehrung .zeiger { display: block; }
.zeiger.klick { scale: .82; transition: transform 700ms var(--kurve), scale 120ms var(--kurve); }

/* Vorschau: nur Bühne und Werte */
.vorschau body { overflow: hidden; height: 100svh; }
.vorschau .nav, .vorschau .kopf .knopf, .vorschau .tags li:nth-child(4) { display: none; }
.vorschau .lernweg ol { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.vorschau .kopf { padding-block: 16px 4px; }
.vorschau .buehne { min-height: 0; }
.vorschau .leiste { padding-block: 10px 16px; }

/* ---------- Reduzierte Bewegung: Formwechsel sofort ---------- */
:root.reduziert * { transition-duration: .01ms !important; animation-duration: .01ms !important; }
.reduziert .zeiger { display: none !important; }

/* ---------- Touch ---------- */
@media (hover: none) {
  .cta:hover { --f: var(--f-cta); background: var(--marke); }
  .cta:active { --f: var(--f-cta-hover); background: var(--marke-tief); }
  [data-v="formen"] .cta:hover { --spitze: 14px; }
  [data-v="formen"] .cta:active { --spitze: 24px; }
}

/* ---------- Schmal ---------- */
@media (max-width: 1100px) {
  .lernweg ol { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
  .buehne { grid-template-columns: 1fr; }
  .bild { min-height: 0; aspect-ratio: 4 / 3; }
  .nav { display: none; }
}
@media (max-width: 520px) {
  .kurs.karte { gap: 18px; }
  .fuss { flex-direction: column; align-items: stretch; }
  .preis { justify-content: space-between; }
  .preis p { text-align: left; }
  .billett { grid-template-columns: minmax(0, 1fr) auto; }
  .abriss { min-width: 92px; padding-inline: 12px; }
  .ticket { padding: 18px; }
  .bild { aspect-ratio: 1; }
  .bild figcaption { font-size: 12.5px; left: 12px; bottom: 12px; }
  .sticker { width: 92px; font-size: 12.5px; right: 14px; top: 14px; }
  .sticker span { font-size: 11px; }
  .leiste { position: sticky; bottom: 0; z-index: 4; background: var(--grund); box-shadow: 0 -1px 0 var(--linie); padding-block: 10px 12px; gap: 8px; }
  .werte { justify-content: flex-start; text-align: left; gap: 2px 12px; }
  .werte [data-w-t] { display: none; }
  .umschalter button { padding: 8px 10px; letter-spacing: .1em; }
}
/* Kontrastmodus: Knöpfe mit Rahmen */
@media (forced-colors: active) { button, [role=button], [role=tab], [role=switch] { border: 1px solid ButtonText !important; } }
</style>
</head>
<body data-ecken="sprache" data-v="basis" data-technik="border-shape">
<header class="kopf">
  <a class="wortmarke" href="#start" aria-label="Rheinknie Kolleg, Startseite">Rheinknie<span class="fahne form" data-form="Fahne im Logo">Kolleg</span></a>
  <nav class="nav" aria-label="Hauptnavigation">
    <a href="#kurse" aria-current="page">Kurse</a><a href="#termine">Termine</a><a href="#team">Über uns</a><a href="#faq">Fragen</a>
  </nav>
  <a class="knopf form" href="#login" data-form="Knopf Anmelden">Anmelden</a>
</header>

<main class="buehne" data-buehne>
  <article class="kurs karte form" data-form="Kurskarte">
    <p class="hand">Online-Kurs · 6 Abende + 2 Zeichenspaziergänge</p>
    <h1>In 6 Wochen zum eigenen <em>Skizzenbuch.</em></h1>
    <p class="lead">Urban Sketching für Erwachsene ohne Vorkenntnisse. Sechs Abende live per Video, dazwischen kurze Übungen für unterwegs. Zum Schluss zeichnen wir gemeinsam am Rheinufer.</p>
    <ul class="tags" aria-label="Merkmale">
      <li class="status gelb form" data-form="Status-Tag">Start 12. Januar</li>
      <li class="status form" data-form="Status-Tag">Hybrid</li>
      <li class="genre form" data-form="Themen-Tag">Zeichnen</li>
      <li class="genre form" data-form="Themen-Tag">Für Anfänger:innen</li>
    </ul>
    <div class="lernweg">
      <p class="mono">Lernweg · 6 Module à 75 min</p>
      <ol>
        <li class="modul form start" data-form="Modul-Kachel" data-bs="Pfeil ohne Kerbe · 5 Punkte · round 4px"><b>Modul 01</b>Linie</li>
        <li class="modul form" data-form="Modul-Kachel" data-bs="Pfeilglied · 6 Punkte · round 4px · Spitze 11px"><b>Modul 02</b>Perspektive</li>
        <li class="modul form" data-form="Modul-Kachel" data-bs="Pfeilglied · 6 Punkte · round 4px · Spitze 11px"><b>Modul 03</b>Licht</li>
        <li class="modul form" data-form="Modul-Kachel" data-bs="Pfeilglied · 6 Punkte · round 4px · Spitze 11px"><b>Modul 04</b>Menschen</li>
        <li class="modul form" data-form="Modul-Kachel" data-bs="Pfeilglied · 6 Punkte · round 4px · Spitze 11px"><b>Modul 05</b>Aquarell</li>
        <li class="modul form" data-form="Modul-Kachel" data-bs="Pfeilglied · 6 Punkte · round 4px · Spitze 11px"><b>Modul 06</b>Draussen</li>
      </ol>
    </div>
    <div class="fuss">
      <div class="person">
        <span class="avatar form" data-form="Avatar">
          <svg viewBox="0 0 80 80" aria-hidden="true">
            <rect width="80" height="80" fill="#f7c325"/>
            <path d="M14 80c2-14 12-21 26-21s24 7 26 21Z" fill="#c2412d"/>
            <path d="M30 56c0 4 4 7 10 7s10-3 10-7" fill="#fbf6ec"/>
            <ellipse cx="40" cy="38" rx="15" ry="18" fill="#fbf6ec" stroke="#141414" stroke-width="1.8"/>
            <path d="M25 36c-1-12 7-19 16-19 9 0 15 6 15 15-6-1-12-5-15-10-3 6-9 11-16 14Z" fill="#141414"/>
            <circle cx="52" cy="15" r="7" fill="#141414"/>
            <circle cx="34" cy="40" r="4.6" fill="none" stroke="#141414" stroke-width="1.6"/>
            <circle cx="46.5" cy="40" r="4.6" fill="none" stroke="#141414" stroke-width="1.6"/>
            <path d="M38.6 40h3.3M35 49c3 2.4 7.6 2.4 10.6 0" fill="none" stroke="#141414" stroke-width="1.6" stroke-linecap="round"/>
            <path d="M60 20l8 22" stroke="#141414" stroke-width="3" stroke-linecap="round"/>
          </svg>
        </span>
        <p><strong>Mirjam Zeller</strong>Illustratorin, unterrichtet seit 2014</p>
      </div>
      <div class="preis">
        <p><strong>CHF 420</strong>oder 3 × CHF 145</p>
        <a class="cta form" href="#buchen" data-form="Button Platz sichern" data-bs="Wegweiser · 5 Punkte · round 6px · Spitze 14 → 24px">Platz sichern
          <svg viewBox="0 0 16 16" aria-hidden="true"><path d="M3 8h9M8.5 4l4 4-4 4" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
        </a>
      </div>
    </div>
  </article>

  <div class="seite">
    <figure class="bild form" data-form="Kursbild">
      <svg class="zeichnung" viewBox="0 0 480 400" preserveAspectRatio="xMidYMax slice" role="img" aria-label="Skizze: Basler Münster über dem Rhein, davor eine Fähre">
        <defs>
          <pattern id="ziegel" width="10" height="8" patternUnits="userSpaceOnUse">
            <rect width="10" height="8" fill="#e9c46a"/><path d="M0 4 5 0l5 4-5 4Z" fill="#3f7f5a"/><path d="M5 0l5 4M0 4l5 4" stroke="#141414" stroke-width=".5"/>
          </pattern>
        </defs>
        <rect width="480" height="400" fill="#fbf6ec"/>
        <!-- Lavierungen, leicht neben den Linien wie beim Aquarell -->
        <path d="M0 0h480v216c-120 18-310-10-480 12Z" fill="#dfe6fb"/>
        <circle cx="146" cy="70" r="24" fill="#f7c325" opacity=".9"/>
        <path d="M190 156h22v108h-22zM216 166h22v98h-22zM240 182h158v82H240z" fill="#e8a58e" opacity=".85"/>
        <path d="M44 214h40v50H44zM90 200h44v64H90zM140 222h40v42h-40z" fill="#efe2cf"/>
        <path d="M0 270c90-8 200 6 300-3s130-5 180-1v134H0Z" fill="#b8c7f0"/>
        <path d="M246 280h30M262 290h70M276 302h48M300 314h24" stroke="#c2412d" stroke-width="3" stroke-linecap="round" opacity=".35"/>
        <!-- Linien -->
        <g fill="none" stroke="#141414" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
          <path d="M150 42a24 24 0 1 1-2 0"/>
          <path d="M252 118q6-6 12 0q6-6 12 0M278 96q5-5 10 0q5-5 10 0M330 128q5-5 10 0q5-5 10 0"/>
          <path d="M0 264c80-2 200 2 300-1s130 0 180 1"/>
          <path d="M184 264V150h22v114M184 150v-6h22v6M188 144l7-66 7 66M195 78v-9"/>
          <path d="M210 264V160h22v104M210 160h22M214 160l7-58 7 58M221 102v-8"/>
          <path d="M191 126h8M191 112h8M217 136h8M217 122h8"/>
          <path d="M232 264v-84h162v84M228 180h170l-14-32H246Z"/>
          <path d="M254 264v-40a10 10 0 0 1 20 0v40M296 264v-44a10 10 0 0 1 20 0v44M338 264v-40a10 10 0 0 1 20 0v40"/>
          <path d="M376 148v-20l8 6v14"/>
          <path d="M374 202l14 0M372 214l18 0M370 226l22 0" stroke-width="1"/>
          <path d="M40 264v-48l20-16 20 16v48M84 264v-62l23-18 23 18v62M134 264v-42l21-14 21 14v42"/>
          <path d="M52 228h6M66 228h6M98 214h6M112 214h6M98 234h6M112 234h6M148 234h6M162 234h6"/>
          <path d="M96 316c14-4 26 4 40 0M240 330c16-4 28 4 42 0M330 346c14-4 26 4 40 0M60 330c12-4 22 4 34 0M392 304c10-3 18 3 28 0"/>
          <path d="M0 30h480" stroke-width="1" opacity=".55"/>
          <path d="M188 280v-36L100 33" stroke-width="1" opacity=".55"/>
          <circle cx="100" cy="30" r="3.5" fill="#dfe6fb"/>
          <path d="M150 298h80l-10 16h-62Z"/>
          <path d="M172 298v-14h30v14M178 284v-6h18v6"/>
        </g>
        <path d="M150 298h80l-10 16h-62Z" fill="#c2412d" opacity=".85"/>
        <path d="M246 148h138l14 32H228Z" fill="url(#ziegel)" opacity=".95"/>
        <path d="M246 148h138l14 32H228Z" fill="none" stroke="#141414" stroke-width="1.6" stroke-linejoin="round"/>
      </svg>
      <figcaption class="hand" data-form="Sprechblase" data-bs="Sprechblase · 7 Punkte · round 10px · Zipfel 10px">Hausaufgabe Modul 05: das Münster, von Kleinbasel aus</figcaption>
      <p class="sticker form" data-form="Sticker" data-bs="Stern · 24 Punkte · round 5px · innen 41 → 35 %">Infoabend<br>27. Nov.<span>online</span></p>
    </figure>

    <div class="billett">
      <div class="ticket form" data-form="Ticket">
        <p class="hand">Dein Platz</p>
        <h2>Urban Sketching</h2>
        <p>Kurs 07 · ab Di, 12. Januar 2027, 18.30 Uhr</p>
      </div>
      <div class="abriss form" data-form="Ticket-Abriss">
        <span class="haken form" data-form="Erfolgs-Häkchen"><svg viewBox="0 0 18 18" aria-hidden="true"><path d="M4 9.5l3.2 3L14 5.5" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
        <small>Gebucht</small>
      </div>
    </div>
  </div>
</main>

<footer class="leiste" data-leiste>
  <div class="gruppe">
  <div class="umschalter v" role="group" aria-label="Variante wählen">
    <button type="button" data-v-wahl="basis" aria-pressed="true">corner-shape</button>
    <button type="button" data-v-wahl="formen" aria-pressed="false">border-shape</button>
  </div>
  <div class="umschalter" role="group" aria-label="Technik wählen" data-teil="formen">
    <button type="button" data-technik-wahl="border-shape" aria-pressed="true">Form</button>
    <button type="button" data-technik-wahl="rueckfall" aria-pressed="false">Rückfall</button>
  </div>
  <div class="umschalter" role="group" aria-label="Eckensprache wählen" data-teil="basis">
    <button type="button" data-variante="sprache" aria-pressed="true">Eckensprache</button>
    <button type="button" data-variante="squircle" aria-pressed="false">Alles Squircle</button>
    <button type="button" data-variante="rund" aria-pressed="false">Nur Rundung</button>
  </div>
  </div>
  <p class="werte mono" data-werte aria-live="polite">
    <span class="wer"><b data-w-name>Kurskarte</b></span>
    <span><i data-w-rl>border-radius</i> <b data-w-r>36px</b></span>
    <span><i data-w-fl>corner-shape</i> <b data-w-f>squircle</b></span>
    <span data-w-t>Wechsel <b>400 ms</b> · cubic-bezier(.37, 0, .63, 1)</span>
  </p>
  <p class="hinweis mono">Dein Browser kennt corner-shape noch nicht: Du siehst die Rückfallebene mit border-radius.</p>
  <p class="hinweis-formen mono">Dein Browser kennt border-shape noch nicht (ab Chrome 147, gerundete Ecken ab 150): Du siehst den Rückfall mit clip-path, ohne Rahmen und Schatten.</p>
</footer>

<svg class="zeiger" data-zeiger viewBox="0 0 18 18" aria-hidden="true"><path d="M2 1.5 15.5 9.2l-6 1.3-2.9 5.6Z" fill="#141414" stroke="#fff" stroke-width="1.2" stroke-linejoin="round"/></svg>

<script>
(() => {
  const html = document.documentElement, body = document.body;
  const reduziert = () => html.classList.contains('reduziert');
  const kann = !!(window.CSS && CSS.supports('corner-shape', 'squircle'));
  if (!kann) document.querySelector('[data-leiste]').classList.add('ohne');
  // border-shape mit gerundetem polygon(): Chrome 147 bzw. 150
  const kannBs = !!(window.CSS && CSS.supports('border-shape', 'polygon(round 1px, 0 0, 100% 0, 50% 100%)'));
  if (!kannBs) document.querySelector('[data-leiste]').classList.add('ohne-bs');

  const knoepfe = [...document.querySelectorAll('[data-variante]')];
  const zeiger = document.querySelector('[data-zeiger]');
  const w = {
    name: document.querySelector('[data-w-name]'), r: document.querySelector('[data-w-r]'),
    f: document.querySelector('[data-w-f]'), t: document.querySelector('[data-w-t]'),
    rl: document.querySelector('[data-w-rl]'), fl: document.querySelector('[data-w-fl]')
  };
  const KURVE = 'cubic-bezier(.37, 0, .63, 1)';
  let gezeigt = null;

  // Werte aus den echten Custom Properties lesen, damit die Anzeige nie von der CSS abweicht
  function werte(el) {
    el = el || document.querySelector('.kurs');
    if (body.dataset.v === 'basis' && !el.classList.contains('form')) el = el.parentElement.closest('.form') || document.querySelector('.kurs');
    gezeigt = el;
    if (body.dataset.v === 'formen' && el.dataset.bs) {
      const echt = kannBs && body.dataset.technik !== 'rueckfall';
      w.name.textContent = el.dataset.form;
      w.rl.textContent = 'Technik'; w.fl.textContent = 'Form';
      w.r.textContent = echt ? 'border-shape' : 'clip-path';
      w.f.textContent = echt ? el.dataset.bs : el.dataset.bs.replace(/ · round \d+px/, '') + ' (ohne Rundung)';
      w.t.innerHTML = (el.classList.contains('cta') || el.classList.contains('sticker') ? 'Hover-Morph <b>300 ms</b> · ' : 'Form <b>statisch</b> · ') + KURVE;
      return;
    }
    w.rl.textContent = 'border-radius'; w.fl.textContent = 'corner-shape';
    const cs = getComputedStyle(el);
    const f = cs.getPropertyValue('--f').trim(), r = cs.getPropertyValue('--r').trim();
    w.name.textContent = el.dataset.form;
    w.r.textContent = r;
    w.f.textContent = kann ? f : f + ' (ignoriert)';
    if (el.classList.contains('cta')) {
      const ruhe = getComputedStyle(body).getPropertyValue('--f-cta').trim();
      const hover = getComputedStyle(body).getPropertyValue('--f-cta-hover').trim();
      w.f.textContent = ruhe === hover ? ruhe : ruhe + ' → ' + hover;
      w.t.innerHTML = 'Hover <b>300 ms</b> · ' + KURVE;
    } else {
      w.t.innerHTML = 'Wechsel <b>400 ms</b> · ' + KURVE;
    }
  }

  function variante(v) {
    body.dataset.ecken = v;
    knoepfe.forEach(k => k.setAttribute('aria-pressed', String(k.dataset.variante === v)));
    werte(gezeigt);
  }
  knoepfe.forEach(k => k.addEventListener('click', e => { if (e.isTrusted) stopp(); variante(k.dataset.variante); }));

  // Varianten nach Regel 13: ?v=basis|formen, unbekannt oder leer → basis
  const VARIANTEN = ['basis', 'formen'];
  const vKnoepfe = [...document.querySelectorAll('[data-v-wahl]')];
  const tKnoepfe = [...document.querySelectorAll('[data-technik-wahl]')];
  const ausUrl = new URLSearchParams(location.search).get('v');
  function setzeV(v, url = true) {
    body.dataset.v = v;
    vKnoepfe.forEach(k => k.setAttribute('aria-pressed', String(k.dataset.vWahl === v)));
    if (v === 'formen') variante('sprache');
    if (url) { const u = new URL(location.href); u.searchParams.set('v', v); history.replaceState(history.state, '', u); }
    werte(v === 'formen' ? document.querySelector('.cta') : null);
  }
  function setzeTechnik(t) {
    body.dataset.technik = t;
    tKnoepfe.forEach(k => k.setAttribute('aria-pressed', String(k.dataset.technikWahl === t)));
    werte(gezeigt);
  }
  vKnoepfe.forEach(k => k.addEventListener('click', e => { if (e.isTrusted) stopp(); setzeV(k.dataset.vWahl); }));
  tKnoepfe.forEach(k => k.addEventListener('click', e => { if (e.isTrusted) stopp(); setzeTechnik(k.dataset.technikWahl); }));

  // Zeigen: Maus und Tippen
  const buehne = document.querySelector('[data-buehne]'), kopf = document.querySelector('.kopf');
  [buehne, kopf].forEach(z => {
    z.addEventListener('pointerover', e => { const el = e.target.closest('[data-form]'); if (el && e.isTrusted) werte(el); });
    z.addEventListener('focusin', e => { const el = e.target.closest('[data-form]'); if (el) werte(el); });
  });
  document.querySelectorAll('a[href^="#"]').forEach(a => a.addEventListener('click', e => e.preventDefault()));

  // Vorführung: ein gedachter Zeiger zeigt Elemente, fährt über den Button und schaltet die Eckensprachen um
  let uhr = null, schritt = 0, an = false;
  const mitte = sel => { const r = document.querySelector(sel).getBoundingClientRect(); return [r.left + r.width * .5, r.top + r.height * .55]; };
  const fahre = sel => { const [x, y] = mitte(sel); zeiger.style.transform = `translate(${x - 3}px, ${y - 2}px)`; };
  const zeige = sel => { document.querySelectorAll('.zeige').forEach(n => n.classList.remove('zeige')); if (sel) { const el = document.querySelector(sel); el.classList.add('zeige'); werte(el); } };
  const klick = sel => { zeiger.classList.add('klick'); setTimeout(() => zeiger.classList.remove('klick'), 160); document.querySelector(sel).click(); };
  const ABLAUF = [
    [700,  () => fahre('.cta')],
    [700,  () => zeige('.cta')],
    [1500, () => { zeige(null); fahre('.ticket'); }],
    [600,  () => werte(document.querySelector('.ticket'))],
    [1100, () => fahre('.sticker')],
    [600,  () => werte(document.querySelector('.sticker'))],
    [1000, () => fahre('[data-variante="squircle"]')],
    [800,  () => klick('[data-variante="squircle"]')],
    [1400, () => fahre('.cta')],
    [700,  () => zeige('.cta')],
    [1200, () => { zeige(null); fahre('[data-variante="rund"]'); }],
    [800,  () => klick('[data-variante="rund"]')],
    [600,  () => { fahre('.ticket'); }],
    [700,  () => werte(document.querySelector('.ticket'))],
    [1300, () => fahre('[data-variante="sprache"]')],
    [800,  () => klick('[data-variante="sprache"]')],
    [600,  () => fahre('.avatar')],
    [700,  () => werte(document.querySelector('.avatar'))],
    [1400, () => {}]
  ];
  // Vorführung der Variante „formen“: Wegweiser, Stern, Pfeilkette, Sprechblase, dann Rückfall und zurück
  const ABLAUF_FORMEN = [
    [700,  () => fahre('.cta')],
    [700,  () => zeige('.cta')],
    [1500, () => { zeige(null); fahre('.sticker'); }],
    [700,  () => zeige('.sticker')],
    [1500, () => { zeige(null); fahre('.modul:nth-child(3)'); }],
    [700,  () => werte(document.querySelector('.modul:nth-child(3)'))],
    [1300, () => fahre('figcaption')],
    [700,  () => werte(document.querySelector('figcaption'))],
    [1200, () => fahre('[data-technik-wahl="rueckfall"]')],
    [800,  () => klick('[data-technik-wahl="rueckfall"]')],
    [600,  () => fahre('.sticker')],
    [700,  () => werte(document.querySelector('.sticker'))],
    [1600, () => fahre('[data-technik-wahl="border-shape"]')],
    [800,  () => klick('[data-technik-wahl="border-shape"]')],
    [1400, () => fahre('.cta')]
  ];
  function takt() {
    const liste = body.dataset.v === 'formen' ? ABLAUF_FORMEN : ABLAUF;
    const [dauer, tu] = liste[schritt % liste.length];
    tu();
    schritt = (schritt + 1) % liste.length;
    uhr = setTimeout(takt, dauer);
  }
  function vorfuehren() {
    pause();
    an = true; schritt = 0;
    html.classList.add('vorfuehrung');
    variante('sprache'); setzeTechnik('border-shape'); zeige(null); werte(null);
    const [x, y] = mitte('.lead'); zeiger.style.transition = 'none'; zeiger.style.transform = `translate(${x}px, ${y}px)`;
    zeiger.getBoundingClientRect(); zeiger.style.transition = '';
    uhr = setTimeout(takt, 400);
  }
  function pause() { clearTimeout(uhr); uhr = null; }
  function weiter() { if (an && !uhr) uhr = setTimeout(takt, 200); }
  function stopp() { pause(); an = false; html.classList.remove('vorfuehrung'); zeige(null); }
  function neustart() { stopp(); variante('sprache'); setzeTechnik('border-shape'); werte(null); }

  setzeV(VARIANTEN.includes(ausUrl) ? ausUrl : VARIANTEN[0], false);

})();
</script>
</body>
</html>