/* ---------------------------------------------------------------------------
   Community-Portal - Oberflaeche

   Farben, Schrift und Mark kommen aus der Docs-Site
   (docs-site/src/css/custom.css, Variante E vom 2026-08-16). Zwei Regeln von
   dort gelten hier genauso:

     Der Akzent traegt auf Dunkel #8E77FF, nicht das Editor-Blau. Das Blau ist
     ein Theme des Werkzeugs und kann die Marke nicht tragen.

     Inter Variable wird selbst ausgeliefert, nicht von Google geholt - die
     Wortmarke ist aus dieser Schrift gebaut.

   Aufbau und Maßstab (Karten, Seitenleiste, Pillen) folgen Meshy Creative Lab
   und der ElevenLabs-App.
--------------------------------------------------------------------------- */

@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('fonts/inter-var-latin.woff2') format('woff2-variations');
}

:root {
  /* Marke - der Akzent auf dunklem Grund */
  --accent: #8e77ff;
  --accent-strong: #a491ff;
  --accent-soft: rgba(142, 119, 255, 0.16);
  --accent-line: rgba(142, 119, 255, 0.38);
  --accent-ink: #120f1c;

  /* Grund und Tinte */
  --bg: #0e0d12;
  --bg-soft: #131218;
  --surface: #17161d;
  --surface-2: #211f2a;
  --line: #272531;
  --line-strong: #3a3747;
  --text: #eeecf3;
  --text-dim: #a9a4b6;
  /* 5.4:1 auf dem Grund, 5.0:1 auf einer Flaeche - vorher 3.6:1 bzw. 3.4:1,
     unter der WCAG-Grenze fuer genau den kleinen Text (Zahlen, Datum, Fuss),
     der diese Farbe traegt. */
  --text-faint: #8a8497;
  --surface-hover: #2a2836;

  /* Signale wie im Werkzeug: Gruen heisst "in Ordnung" */
  --ok: #3bd3a3;
  --warn: #fb923c;
  --danger: #f2706b;

  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 16px;
  --radius-pill: 999px;

  /* HOEHEN. Geschichtete Schatten statt eines einzigen weichen Flecks: ein
     enger fuer die Kante, ein weiter fuer die Hoehe - so liegt eine Karte
     auf dem Grund, statt in einem Nebel zu schweben. Die Lichtkante oben
     (`--highlight`) gibt dunklen Flaechen eine Oberseite. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.45), 0 4px 12px -4px rgba(0, 0, 0, 0.4);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 22px 44px -14px rgba(0, 0, 0, 0.7);
  --highlight: inset 0 1px 0 rgba(255, 255, 255, 0.045);
  --glow: 0 0 0 1px var(--accent-line), 0 18px 40px -14px rgba(142, 119, 255, 0.45);

  /* Signaltoene fuer Flaechen - vorher als rgba-Literale an elf Stellen. */
  --danger-soft: rgba(242, 112, 107, 0.12);
  --danger-line: rgba(242, 112, 107, 0.34);
  --scrim: rgba(6, 5, 10, 0.72);

  /* SCHRIFTGROESSEN. 22 verschiedene Pixelwerte standen im Stylesheet; die
     Grundbausteine lesen jetzt aus dieser Skala. */
  --fs-xs: 12px;
  --fs-sm: 13px;
  --fs-md: 14px;
  --fs-base: 15px;
  --fs-lg: 17px;
  --fs-xl: 22px;
  --fs-2xl: 28px;
  --fs-3xl: 40px;

  /* Bewegung: kurz, ohne Nachfedern, am Ende weich. Wer weniger Bewegung
     eingestellt hat, bekommt alles auf einen Schlag (Abschnitt "Bewegung"
     ganz unten). */
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in-out: cubic-bezier(0.45, 0, 0.2, 1);
  --dur-fast: 120ms;
  --dur: 180ms;
  --dur-slow: 280ms;
  /* Breite des Inhalts. Der Katalog hebt sie fuer sich an - ein Gitter darf
     breiter stehen als ein Absatz, den jemand lesen soll. */
  --page: 1280px;
  --page-wide: 1640px;
  --gutter: 28px;

  /* Was vorher als Literal in einzelnen Regeln stand und in Hell etwas
     anderes sein muss. */
  --accent-lift: #b3a3ff;
  --accent-cast: rgba(142, 119, 255, 0.75);
  --accent-cast-strong: rgba(142, 119, 255, 0.9);
  --header-bg: rgba(14, 13, 18, 0.72);
  --row-hover: rgba(255, 255, 255, 0.02);
  --selection-bg: rgba(142, 119, 255, 0.38);
  --selection-ink: #ffffff;

  /* ── AUF DER BUEHNE ──────────────────────────────────────────────────
     Diese Werte wechseln NICHT mit dem Thema, und das ist ihr ganzer
     Sinn. Die Buehne bleibt dunkel - ein Viewport, wie ihn Blender und
     Unity zwei Fenster weiter auch haben -, und was auf ihr liegt, muss
     mit ihr lesbar bleiben: die Dauerpille auf einer Vorschau, die
     Schalter am Rand, der leere Rahmen, wenn ein Clip nicht laedt.

     Ohne sie stuende in Hell heller Text auf einem dunklen Bild - nicht
     als Fehler in einer Regel, sondern als Folge davon, dass dieselbe
     Marke zwei verschiedene Untergruende meinen muesste. */
  --on-stage-ink: #eeecf3;
  --on-stage-dim: #a9a4b6;
  --on-stage-faint: #8a8497;
  --on-stage-line: #3a3747;
  --on-stage-accent: #8e77ff;
  --on-stage-accent-line: rgba(142, 119, 255, 0.38);
  --on-stage-accent-veil: rgba(142, 119, 255, 0.14);
  --on-stage-scrim: rgba(14, 13, 18, 0.72);
  --on-stage-scrim-strong: rgba(14, 13, 18, 0.84);
  --stage-void: #0e0d12;


  color-scheme: dark;
}

/* ══════════════════════════════════════════════════════════════════════
   HELL

   Kein zweites Stylesheet und keine Kopie der Regeln: derselbe Satz
   Marken, andere Werte. Was hier NICHT noch einmal steht, gilt weiter -
   Radien, Schriftgroessen, Bewegung, und die Buehnenfarben.

   WER UMSCHALTET, STEHT IN `theme.js`. Das Attribut ist die einzige
   Weiche; eine zweite Fassung dieser Werte unter `prefers-color-scheme`
   waere dieselbe Palette an zwei Orten und liefe beim ersten Nachbessern
   auseinander.

   DIE ZAHLEN SIND GEMESSEN, nicht geschaetzt - der dunkle Satz traegt an
   `--text-faint` eine Notiz darueber, dass 3.6:1 zu wenig waren, und
   dieselbe Latte gilt hier. Auf `--bg`: Text 16.8:1, `--text-dim` 6.6:1,
   `--text-faint` 5.4:1, Akzent 6.2:1, Gruen 5.4:1, Orange 5.5:1, Rot
   5.4:1. Weiss auf dem Akzentknopf 6.6:1, auf seinem hellsten
   Verlaufsende noch 4.9:1.

   DER AKZENT IST EIN ANDERER. #8E77FF steht auf Weiss bei 2.6:1 - als
   Flaeche schoen, als Link unlesbar. Hell traegt deshalb ein dunkleres
   Violett derselben Familie. Die Marke selbst bleibt beim hellen Ton;
   sie liegt nie auf Weiss.
   ══════════════════════════════════════════════════════════════════════ */
:root[data-theme="light"] {
  --accent: #5f3fd6;
  --accent-strong: #6b4ae0;
  --accent-lift: #7358e6;
  --accent-soft: rgba(95, 63, 214, 0.10);
  --accent-line: rgba(95, 63, 214, 0.30);
  --accent-ink: #ffffff;
  --accent-cast: rgba(95, 63, 214, 0.30);
  --accent-cast-strong: rgba(95, 63, 214, 0.40);

  --bg: #f7f6fa;
  --bg-soft: #f1eff6;
  --surface: #ffffff;
  --surface-2: #f4f2f9;
  --surface-hover: #ebe8f3;
  --line: #e2dfec;
  --line-strong: #cdc8dc;
  --text: #17151f;
  --text-dim: #5b5570;
  --text-faint: #676180;

  --ok: #0a7355;
  --warn: #9a5205;
  --danger: #bd302b;
  --danger-soft: rgba(189, 48, 43, 0.10);
  --danger-line: rgba(189, 48, 43, 0.30);

  /* Schatten auf Hell sind eine Frage der Dosis: derselbe Schwarzanteil
     wie in Dunkel waere ein Schmutzrand. Ein Hauch Violett darin, damit
     sie neben dem Grund nicht grau stehen. */
  --shadow-sm: 0 1px 2px rgba(28, 22, 50, 0.06), 0 4px 12px -4px rgba(28, 22, 50, 0.10);
  --shadow: 0 1px 2px rgba(28, 22, 50, 0.06), 0 22px 44px -14px rgba(28, 22, 50, 0.16);
  /* Die Lichtkante dreht sich um: auf Dunkel hebt sie die Oberseite an,
     auf Hell ist sie das Weiss, mit dem eine Flaeche vom Grund abhebt. */
  --highlight: inset 0 1px 0 rgba(255, 255, 255, 0.75);
  --glow: 0 0 0 1px var(--accent-line), 0 18px 40px -14px rgba(95, 63, 214, 0.28);
  --scrim: rgba(24, 20, 40, 0.42);

  --header-bg: rgba(247, 246, 250, 0.78);
  --row-hover: rgba(24, 20, 40, 0.035);
  --selection-bg: rgba(95, 63, 214, 0.22);
  --selection-ink: #17151f;

  color-scheme: light;
}

html { font-feature-settings: 'cv05' 1, 'cv08' 1, 'ss03' 1; }

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }
/* Unsichtbare Tooltips (`[data-tip]::after`) liegen mit voller Breite im
   Layout; an einem Knopf am rechten Rand schoben sie die Seite 35 px ueber
   den Bildschirm hinaus - ein waagerechter Scrollbalken auf jedem Telefon.
   `clip` statt `hidden`: es macht kein Scroll-Element daraus, der klebende
   Kopf klebt weiter. */
html { overflow-x: clip; scrollbar-color: var(--line-strong) transparent; }
::selection { background: var(--selection-bg); color: var(--selection-ink); }

body {
  /* Ein Schein im Akzent ganz oben - er gibt der Seite eine Lichtquelle, statt
     sie als flaches Schwarz stehen zu lassen. Er scrollt mit und ist nach
     einem Bildschirm vorbei. */
  background:
    radial-gradient(1100px 520px at 50% -200px, color-mix(in srgb, var(--accent) 12%, transparent), transparent 70%),
    var(--bg);
  color: var(--text);
  font: 16px/1.6 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

.hidden { display: none !important; }

/* TASTATUR-FOKUS. Eingabefelder hatten einen eigenen Ring, Icon-Knoepfe,
   Schlagworte, Chips und Reiter nur den des Browsers - auf diesem Grund
   praktisch unsichtbar. Jetzt ein Ring fuer alles, was man anfassen kann,
   aber nur fuer die Tastatur (:focus-visible), nicht nach jedem Mausklick. */
a:focus-visible, button:focus-visible, summary:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: 12px;
  top: -48px;
  z-index: 100;
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}
.skip-link:focus-visible { top: 12px; }

/* Fuer Screenreader da, fuer das Auge nicht - die Seitenueberschrift von
   Katalog und Sammlungen, seit der Reiter oben sie sichtbar vertritt. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── Kopfleiste ────────────────────────────────────────────────────────
   Oben statt links. Die feste Spalte links war das Muster einer App; das
   Portal ist aber das Schaufenster vor der App, und der Katalog ist die
   Ansicht, bei der jede gesparte Breite unmittelbar eine Karte mehr pro
   Reihe bedeutet. Meshy Creative Lab und Mixamo tragen ihre Navigation
   beide oben.

   Vier Blöcke in einer Zeile: Marke, Navigation, Suche, Konto. Die Suche
   nimmt den Platz, der übrig bleibt, und ist als einzige elastisch - bei
   wenig Raum schrumpft sie, statt dass etwas umbricht.
--------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--header-bg);
  backdrop-filter: saturate(150%) blur(16px);
  border-bottom: 1px solid var(--line);
}

/* KEINE Seitenbreite hier. Der Kopf ist ein Band ueber die volle Breite, und
   die Marke sitzt an seinem linken Rand. Vorher galt fuer ihn dieselbe
   `--page`-Breite wie fuer einen Absatz: auf einem 1600er Schirm stand die
   Marke damit 160 px eingerueckt und wirkte verrutscht - auf dem Katalog, der
   `--page-wide` nutzt, sogar gegenueber dem Inhalt DARUNTER. Ein Absatz
   braucht sein Lesemass, ein Band nicht. */
.header-inner {
  padding: 0 var(--gutter);
  height: 60px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  margin-right: 12px;
  color: var(--text);
}
.brand:hover { text-decoration: none; }

/* Das Lockup haelt seinen Freiraum: ein Viertel der eigenen Hoehe ringsum. */
.brand-lockup { width: 150px; height: auto; display: block; }
.brand-mark { width: 28px; height: 28px; display: none; }

/* DIE MARKE IN TINTE. Die ausgelieferte Datei ist die weisse - sie steht auf
   dem dunklen Grund, und das ist der Normalfall. Auf Hell waere sie weiss auf
   fast weiss, also unsichtbar.

   `content` tauscht das Bild, statt ein zweites in den Kopf zu legen: so
   bleibt EIN Element im Dokument und der Browser holt nur die Fassung, die er
   zeigt. Die Adresse ist relativ zu DIESER Datei und traegt damit denselben
   Stempel wie alles andere unter /assets - eine absolute stuende ohne ihn da
   und laege nach dem naechsten Build im Cache fest. */
:root[data-theme="light"] .brand-lockup { content: url("brand/aw-lockup-tinte.svg"); }
:root[data-theme="light"] .brand-mark { content: url("brand/aw-mark-tinte.svg"); }
.brand small {
  color: var(--text-faint);
  font-weight: 600;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-left: 1px solid var(--line-strong);
  padding-left: 8px;
}

.site-nav { display: flex; align-items: center; gap: 2px; flex: none; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  color: var(--text-dim);
  font-size: 14.5px;
  font-weight: 500;
  white-space: nowrap;
}
.nav-item:hover { background: var(--surface); color: var(--text); text-decoration: none; }
.nav-item.active { background: var(--surface-2); color: var(--text); }
.nav-item.active .nav-icon { color: var(--accent); }
.nav-icon { width: 18px; height: 18px; flex: none; color: var(--text-faint); }

/* ── Suche im Kopf ─────────────────────────────────────────────────────
   Ein gewöhnliches GET-Formular auf den Katalog. Das `kbd` nennt die Taste,
   die hierher springt, und verschwindet, sobald das Feld den Fokus hat -
   dann ist die Auskunft erledigt.
--------------------------------------------------------------------------- */

.header-search {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 460px;
  margin-inline: auto;
  position: relative;
  display: flex;
  align-items: center;
}
.header-search svg {
  position: absolute;
  left: 13px;
  width: 17px;
  height: 17px;
  color: var(--text-faint);
  pointer-events: none;
}
.header-search input {
  width: 100%;
  min-height: 38px;
  padding: 0 38px 0 38px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  font-size: 14.5px;
}
.header-search input:focus { background: var(--bg-soft); }
.header-search kbd {
  position: absolute;
  right: 12px;
  font: inherit;
  font-size: 12px;
  line-height: 1;
  color: var(--text-faint);
  border: 1px solid var(--line-strong);
  border-radius: 5px;
  padding: 3px 6px;
  pointer-events: none;
}
.header-search input:focus ~ kbd,
.header-search input:not(:placeholder-shown) ~ kbd { display: none; }

.header-account { flex: none; display: flex; align-items: center; gap: 8px; margin-left: 4px; }

/* DER UMSCHALTER. Er traegt beide Zeichen im Markup und zeigt immer das,
   WOHIN es geht - in Dunkel die Sonne, in Hell den Mond. Das spart das
   Nachmalen per Skript und damit die Trusted-Types-Frage; die Auswahl ist
   eine Regel, kein Austausch.

   `hidden` steht im HTML: ohne `theme.js` schaltet hier nichts, und ein
   Knopf, der nichts tut, ist schlimmer als keiner. Das Skript nimmt es
   weg, sobald es laeuft. */
.theme-toggle {
  flex: none;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-dim);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.theme-toggle:hover { color: var(--text); border-color: var(--line-strong); }
.theme-toggle svg { width: 18px; height: 18px; }
.theme-toggle .theme-moon { display: none; }
:root[data-theme="light"] .theme-toggle .theme-moon { display: block; }
:root[data-theme="light"] .theme-toggle .theme-sun { display: none; }

.account { display: flex; align-items: center; gap: 8px; }

.account-name {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 190px;
  padding: 4px 10px 4px 4px;
  border-radius: var(--radius-pill);
  color: var(--text);
  font-size: 14px;
}
.account-name:hover { background: var(--surface); text-decoration: none; }
.account-name > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.avatar {
  width: 28px;
  height: 28px;
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent);
  font-weight: 700;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
}

img.avatar { object-fit: cover; padding: 0; background: var(--surface-2); }

.badge {
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: var(--radius-pill);
  padding: 3px 10px;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.badge:hover { text-decoration: none; background: color-mix(in srgb, var(--accent) 26%, transparent); }

.icon-button { min-height: 32px; padding: 0 10px; font-size: 14px; }

/* Schmale Fenster: die Wortmarke weicht der Bildmarke, die Beschriftungen der
   Navigation weichen ihren Symbolen. Die Suche bleibt - sie ist der Grund,
   warum die Leiste oben liegt. */
@media (max-width: 1080px) {
  .brand-lockup, .brand small { display: none; }
  .brand-mark { display: block; }
  .nav-item span { display: none; }
  .nav-item { padding: 8px 10px; }
  .nav-icon { width: 20px; height: 20px; }
  .account-name > span:last-child { display: none; }
  .account-name { padding: 4px; }
}
/* Auf einem Telefon passt die Suche nicht neben Marke, Navigation und Konto -
   sie wurde vom Anmelde-Knopf ueberschrieben. Also zwei Zeilen: oben, wer und
   wohin, darunter die Suche ueber die ganze Breite. */
@media (max-width: 620px) {
  .header-inner {
    flex-wrap: wrap;
    height: auto;
    padding-block: 10px 12px;
    row-gap: 10px;
  }
  .header-search {
    order: 3;
    flex-basis: 100%;
    max-width: none;
    margin-inline: 0;
  }
  .header-search kbd { display: none; }
  .header-account { margin-left: auto; }
  .site-nav { gap: 0; }
  .header-account .button { padding: 0 14px; font-size: 14px; }

  /* Seit "Collections" als zweiter Reiter oben steht, passte angemeldet
     "2 messages" nicht mehr in die erste Zeile - der Kontoblock rutschte in
     eine eigene. Hier steht nur die Zahl; der Satz bleibt im Text (fuer
     Screenreader) und als Tooltip. */
  .badge[data-count] { font-size: 0; padding: 3px 8px; }
  .badge[data-count]::before { content: attr(data-count); font-size: 11.5px; }
}

/* ── Seitengerüst ──────────────────────────────────────────────────────
   `--page` ist die Breite des Inhalts, `--gutter` sein Rand. Der Katalog
   setzt `--page` auf seinen eigenen Wert hoch: ein Gitter darf breiter
   stehen als ein Absatz, den man lesen soll.
--------------------------------------------------------------------------- */

main {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding: 36px var(--gutter) 80px;
  flex: 1;
}

/* Der Katalog (zugleich die Startseite) und die Sammlungen stellen Ware aus,
   keinen Fliesstext: dort bedeutet jede zusaetzliche Breite eine Karte mehr
   pro Reihe. */
main.wide { max-width: var(--page-wide); }

.site-footer {
  border-top: 1px solid var(--line);
  color: var(--text-faint);
  font-size: 13px;
}
.footer-inner {
  max-width: var(--page);
  margin-inline: auto;
  padding: 24px var(--gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 22px;
}
.footer-share { margin: 0; flex: 1 1 320px; }
.footer-share strong { color: var(--text-dim); }
.footer-share em { color: var(--text-dim); font-style: normal; }
.footer-links { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.site-footer a { color: var(--text-faint); }
.site-footer a:hover { color: var(--text-dim); }

/* ── Typografie ────────────────────────────────────────────────────────── */

h1 {
  font-size: var(--fs-3xl);
  line-height: 1.1;
  letter-spacing: -0.028em;
  font-weight: 800;
  margin: 0 0 10px;
}

h2 {
  font-size: 20px;
  line-height: 1.3;
  letter-spacing: -0.018em;
  font-weight: 800;
  margin: 36px 0 14px;
}

.lead { color: var(--text-dim); font-size: 16px; margin: 0 0 28px; max-width: 62ch; }
.muted { color: var(--text-dim); }
.faint { color: var(--text-faint); }
.small { font-size: var(--fs-sm); }

/* Ein Akzentstrich unter der Seitenüberschrift, wie im Kreativlabor. */
main > h1::after, .prose > h1::after {
  content: "";
  display: block;
  width: 64px;
  height: 3px;
  margin-top: 14px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--accent), transparent);
}

/* ── Knöpfe ────────────────────────────────────────────────────────────── */

.button, button {
  font: inherit;
  font-weight: 600;
  font-size: var(--fs-base);
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  box-shadow: var(--highlight);
  color: var(--text);
  min-height: 40px;
  padding: 0 18px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}
.button:hover, button:hover { background: var(--surface-hover); border-color: var(--line-strong); text-decoration: none; }
.button:active, button:active { transform: translateY(1px); }

.button.primary, button.primary {
  background: linear-gradient(180deg, var(--accent-strong), var(--accent));
  border-color: var(--accent);
  color: var(--accent-ink);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 8px 22px -10px var(--accent-cast);
}
.button.primary:hover, button.primary:hover {
  background: linear-gradient(180deg, var(--accent-lift), var(--accent-strong));
  border-color: var(--accent-strong);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.26), 0 10px 28px -10px var(--accent-cast-strong);
}

.button.danger, button.danger { border-color: color-mix(in srgb, var(--danger) 50%, transparent); color: var(--danger); background: transparent; box-shadow: none; }
.button.danger:hover, button.danger:hover { background: var(--danger-soft); }

.button.ghost, button.ghost { background: transparent; border-color: var(--line); color: var(--text-dim); box-shadow: none; }
.button.ghost:hover, button.ghost:hover { color: var(--text); background: var(--surface); }

button:disabled { opacity: 0.45; cursor: default; transform: none; }

/* ── Felder ────────────────────────────────────────────────────────────── */

input, select, textarea {
  font: inherit;
  font-size: 15px;
  background: var(--bg-soft);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 9px 13px;
  min-height: 40px;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
input::placeholder, textarea::placeholder { color: var(--text-faint); }
textarea { width: 100%; min-height: 100px; resize: vertical; line-height: 1.5; }

label.field { display: block; margin: 0 0 16px; }
label.field > span { display: block; color: var(--text-dim); font-size: 14px; margin-bottom: 6px; }
label.field input, label.field select { width: 100%; }
label.check { display: flex; gap: 12px; align-items: flex-start; margin: 12px 0; color: var(--text-dim); font-size: 15px; }
label.check input { min-height: 0; margin-top: 4px; accent-color: var(--accent); }

/* ── Flächen ───────────────────────────────────────────────────────────── */

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--highlight);
  border-radius: var(--radius);
  padding: 22px 24px;
}

.notice {
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  margin: 14px 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  font-size: 15px;
}
.notice.error { border-left-color: var(--danger); }
.notice.ok { border-left-color: var(--ok); }
.notice.warn { border-left-color: var(--warn); }

/* ── Meldungen am unteren Rand (AW.toast) ─────────────────────────────── */
/* Unten mittig, ueber allem ausser einem offenen Dialog. Der Stapel selbst
   laesst Klicks durch; nur die Meldungen fangen sie. */
.toasts {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 90;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: max-content;
  max-width: calc(100vw - 32px);
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px 10px 12px;
  border-radius: var(--radius);
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
  color: var(--text);
  box-shadow: var(--shadow);
  font-size: 14px;
}
.toast .icon { width: 18px; height: 18px; flex: none; color: var(--ok); }
.toast.error .icon { color: var(--danger); }
.toast.leaving { opacity: 0; }
.toast-action {
  min-height: 0;
  padding: 2px 4px;
  margin-left: 4px;
  border: 0;
  background: none;
  color: var(--accent);
  font-weight: 600;
  cursor: pointer;
}

.tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0; }
.tag {
  background: var(--surface-2);
  color: var(--text-dim);
  border-radius: var(--radius-pill);
  padding: 4px 13px;
  font-size: 13px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.tag:hover { color: var(--text); background: var(--surface-hover); border-color: var(--line-strong); text-decoration: none; }
.tag.active {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--accent);
}
.tag-count { color: var(--text-faint); margin-left: 7px; font-size: 12px; font-variant-numeric: tabular-nums; }
.tag.active .tag-count { color: var(--accent); opacity: 0.7; }

/* ── Filter- und Schlagwortleiste ──────────────────────────────────────
   Die Sortierung links, was gerade gilt rechts daneben. Das Suchfeld ist
   hier weg - es steht im Kopf und gilt auf jeder Seite.
--------------------------------------------------------------------------- */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 14px;
  align-items: center;
  margin: 0 0 14px;
}
.filter-state { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* Was gerade einschraenkt, mit dem Weg heraus daran. Eine Einschraenkung, die
   man nicht sieht, liest sich als leerer Katalog. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent);
  border-radius: var(--radius-pill);
  padding: 3px 12px;
  font-size: 13px;
  max-width: 320px;
}
.chip:hover { text-decoration: none; background: color-mix(in srgb, var(--accent) 26%, transparent); }
.chip-x { color: var(--text-faint); font-size: 15px; line-height: 1; }
.chip:hover .chip-x { color: var(--accent); }

.tag-bar { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 26px; }

.segmented {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
}
.segmented a, .segmented button {
  border: none;
  background: transparent;
  color: var(--text-dim);
  border-radius: var(--radius-pill);
  min-height: 32px;
  padding: 0 16px;
  font-size: 14px;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}
.segmented a:hover, .segmented button:hover { background: var(--surface); color: var(--text); text-decoration: none; }
.segmented a.active, .segmented button.active { background: var(--surface-2); color: var(--text); box-shadow: var(--shadow-sm), var(--highlight); }

/* ── Katalog ───────────────────────────────────────────────────────────── */

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

.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm), var(--highlight);
  border-radius: var(--radius-lg);
  overflow: hidden;
  color: var(--text);
  display: flex;
  flex-direction: column;
  transition: transform var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out);
}
.card:hover {
  transform: translateY(-3px);
  border-color: var(--accent-line);
  box-shadow: var(--glow), var(--highlight);
  text-decoration: none;
}

/* Die Buehne traegt die Vorschau und was auf ihr liegt - Neu-Marke und Dauer.
   Vorher hingen beide am .card selbst, was sie an den Kartenrand band statt
   an das Bild. */
.card-stage { position: relative; }
.card canvas, .card .viewer-empty {
  width: 100%;
  height: 206px;
  background: radial-gradient(120% 90% at 50% 20%, #1e1c28 0%, #100f15 70%);
  display: block;
}
.card .viewer-empty { display: flex; align-items: center; justify-content: center; color: var(--on-stage-faint); font-size: 13px; }

.card-body { padding: 13px 15px 16px; display: flex; flex-direction: column; gap: 5px; flex: 1; }

/* Der Titel ist der Link auf den Clip, und sein ::after deckt die ganze Karte
   ab - so bleibt die Flaeche anklickbar, ohne dass ein Link im Link stehen
   muss (was HTML nicht erlaubt). Der Autor daneben liegt darueber. */
.card-title {
  font-weight: 650;
  font-size: 15.5px;
  letter-spacing: -0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.card-title::after { content: ""; position: absolute; inset: 0; }
.card-title:hover { text-decoration: none; }
.card:hover .card-title { color: var(--accent-strong); }

/* Ein Fokus, den man sieht: ohne ihn ist die Karte per Tastatur zwar
   erreichbar, aber nicht auffindbar. */
.card:focus-within { border-color: var(--accent-line); }
.card-title:focus-visible, .card-author:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 3px;
}
.card-meta { color: var(--text-dim); font-size: var(--fs-sm); display: flex; gap: 7px; flex-wrap: wrap; align-items: center; justify-content: space-between; }
.card-meta .dot { color: var(--text-faint); }
/* Der Autor auf der Karte fuehrt zu allem anderen derselben Person. Er sieht
   erst beim Hinsehen wie ein Link aus - sonst konkurriert er mit dem Titel um
   die Aufmerksamkeit, und der ist das Angebot. */
/* Liegt ueber der Flaeche, die der Titel abdeckt - sonst waere er nicht zu
   treffen. */
.card-author { color: var(--text-dim); font-weight: 500; position: relative; z-index: 1; }
.card-author:hover { color: var(--accent); text-decoration: underline; }

.card-flag, .card-duration {
  position: absolute;
  top: 11px;
  background: var(--on-stage-scrim-strong);
  border: 1px solid var(--on-stage-line);
  color: var(--on-stage-ink);
  border-radius: var(--radius-pill);
  padding: 2px 10px;
  font-size: 12px;
  font-weight: 600;
  /* Kein backdrop-filter: die Pille liegt auf einer Leinwand, die bis zu 30-mal
     in der Sekunde neu gezeichnet wird, und jede Pille muesste ihr Stueck
     jedes Mal neu weichzeichnen - bei 24 Karten 48 Mal. Bei 84 % Deckkraft
     sah man den Unterschied ohnehin kaum. */
}
.card-flag { left: 11px; }
/* Wie die Laufzeit auf einem Video: unten rechts, auf dem Bild. */
.card-duration {
  top: auto;
  bottom: 11px;
  right: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
}

/* ── Wenn eine Adresse ins Leere fuehrt ────────────────────────────────
   Zwei Dinge muss eine Fehlerseite tun: sagen, was los ist, und einen Weg
   anbieten. Der Weg fuehrt in den Katalog, der zugleich die Startseite ist -
   wer einen Clip gesucht hat, sucht weiter Clips.
--------------------------------------------------------------------------- */

.notfound { padding: 60px 0 40px; max-width: 54ch; }
.notfound-code {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--accent);
  margin: 0 0 8px;
}
.notfound h1 { font-size: 34px; }
.notfound h1::after { content: none; }
.notfound .lead { margin-bottom: 26px; }

.pager { display: flex; justify-content: center; align-items: center; gap: 12px; margin: 36px 0 0; }
.empty { text-align: center; color: var(--text-dim); padding: 56px 0; display: flex; flex-direction: column; align-items: center; gap: 16px; }
.empty p { margin: 0; }

/* ── Clip-Seite ────────────────────────────────────────────────────────
   Links die Bewegung und das Gespräch darunter, rechts was man mitnimmt.
   Die rechte Spalte klebt beim Scrollen: durch ein langes Gespräch zu
   scrollen darf den Weg ins eigene Projekt nicht aus dem Bild schieben.
--------------------------------------------------------------------------- */

.clip-layout { display: grid; grid-template-columns: minmax(0, 1fr) 352px; gap: 32px; align-items: start; }
@media (max-width: 960px) { .clip-layout { grid-template-columns: 1fr; } }

.clip-main { min-width: 0; }
.clip-side { position: sticky; top: 76px; display: flex; flex-direction: column; gap: 20px; }
@media (max-width: 960px) { .clip-side { position: static; } }

.clip-layout h1 { font-size: 27px; margin: 18px 0 0; }
.clip-layout h1::after { content: none; }

/* Wer, wann, und was man tun kann - eine Zeile unter dem Titel. */
.clip-byline {
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 12px 0 18px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
.clip-author { font-weight: 600; font-size: 15px; }
.clip-actions { margin-left: auto; display: flex; flex-wrap: wrap; gap: 8px; }

.clip-description { color: var(--text-dim); margin: 14px 0 0; white-space: pre-wrap; max-width: 72ch; }

.get-panel { display: flex; flex-direction: column; gap: 14px; }
.get-panel .actions { display: flex; flex-direction: column; gap: 8px; margin: 0; }
.get-panel .actions .button, .get-panel .actions button { width: 100%; justify-content: center; }
.get-panel .actions p { margin: 0; }

/* EIN Download-Knopf, dahinter die Formate (clip-download.js). */
.download-button { width: 100%; justify-content: center; gap: 8px; }
.download-button .icon { width: 18px; height: 18px; }
.popover.format-popover { max-width: 360px; min-width: 300px; padding: 6px; }
.format-sheet { display: flex; flex-direction: column; gap: 2px; }
.format-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 0;
  padding: 10px 12px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.format-row:hover:not(:disabled) { background: var(--surface-2); border-color: var(--line); }
.format-row:disabled { cursor: default; opacity: 0.6; }
.format-row .icon { width: 18px; height: 18px; flex: none; color: var(--text-dim); }
.format-row:hover:not(:disabled) .icon { color: var(--accent); }
.format-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.format-text strong { font-weight: 600; font-size: 14px; }
.format-tag {
  flex: none;
  font-size: 11.5px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong);
  color: var(--text-dim);
}

/* ── Nachbarschaft ─────────────────────────────────────────────────────
   Wer einen Laufzyklus ansieht, will meistens Laufzyklen sehen. Zeilen, keine
   Karten: die Spalte ist 352 px breit, und eine Vorschau je Nachbar wäre ein
   weiterer WebGL-Kontext für eine Nebensache.
--------------------------------------------------------------------------- */

.related h2 { font-size: 15px; margin: 0 0 10px; }
.related-list { display: flex; flex-direction: column; gap: 2px; }
.related-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  color: var(--text);
}
.related-item:hover { background: var(--surface); text-decoration: none; }
.related-title { font-size: 14.5px; font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.related-meta { color: var(--text-faint); font-size: 12.5px; }

/* ── Das Gespräch ──────────────────────────────────────────────────────
   Flach, älteste zuerst. Der Avatar trägt die Spalte links, damit mehrere
   Kommentare als Gespräch lesbar bleiben und nicht als Liste von Abschnitten.
--------------------------------------------------------------------------- */

.comments { margin-top: 40px; max-width: 76ch; }
.comments h2 { margin: 0 0 16px; }

.comment-compose, .comment { display: flex; gap: 12px; }
.comment-compose { margin-bottom: 26px; }
.compose-body { flex: 1; min-width: 0; }
.compose-body textarea { min-height: 78px; margin: 0; }
.compose-foot { display: flex; align-items: center; justify-content: flex-end; gap: 12px; margin-top: 8px; }

.comment-signin {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 26px;
}

.comment-list { display: flex; flex-direction: column; gap: 20px; }
.comment-body { flex: 1; min-width: 0; }
.comment-head { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.comment-head strong, .comment-author { font-size: 14.5px; font-weight: 700; color: var(--text); }
.comment-author:hover { color: var(--accent); }
.comment-more { align-self: flex-start; }
.comment-text { margin: 4px 0 0; color: var(--text-dim); white-space: pre-wrap; overflow-wrap: anywhere; }
.comment-empty { margin: 0; }

/* Die eigenen Handlungen erscheinen erst beim Hinsehen - sie sind sonst so
   auffällig wie der Name darüber. */
.link-button {
  border: none;
  background: none;
  color: var(--text-faint);
  padding: 0;
  min-height: 0;
  font-size: 13px;
  font-weight: 500;
  opacity: 0;
}
.comment:hover .link-button, .link-button:focus-visible { opacity: 1; }
.link-button:hover { background: none; color: var(--text); text-decoration: underline; transform: none; }
@media (hover: none) { .link-button { opacity: 1; } }

.viewer {
  background: radial-gradient(120% 90% at 50% 15%, #1e1c28 0%, #0f0e14 70%);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.viewer .stage { position: relative; }
/* pan-y: senkrecht wischen scrollt die Seite, waagerecht dreht die Figur. Mit
   `none` war die Buehne auf dem Telefon eine 360 px hohe Wand, an der das
   Scrollen endete. */
/* WENIGER BREITBILD. Hier stand eine feste Hoehe von 480 px bei voller
   Spaltenbreite - auf einer breiten Seite wurde die Buehne damit 2,6:1, ein
   Streifen mit einer schmalen Figur in der Mitte. Jetzt ein Seitenverhaeltnis,
   gedeckelt auf die Fensterhoehe (Kopf, Abstand und Transportleiste abgezogen),
   damit Leiste und Figur zusammen im Bild bleiben. */
.viewer canvas {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  max-height: calc(100svh - 170px);
  min-height: 320px;
  display: block;
  cursor: grab;
  touch-action: pan-y;
}
.viewer > .viewer-empty { height: auto; aspect-ratio: 16 / 10; max-height: calc(100svh - 170px); min-height: 320px; }
.viewer canvas:active { cursor: grabbing; }
/* Mittlere Maustaste gedrueckt: die Kamera verschiebt (stage.js, panBy). */
.viewer canvas.is-panning { cursor: move; }

/* Tempo steht als Zahl im Knopf; alles ausser 1x ist hervorgehoben, damit
   niemand vergisst, dass er langsamer schaut. */
.speed-toggle { width: auto; min-width: 42px; padding: 0 8px; font-size: 12.5px; font-weight: 650;
  font-variant-numeric: tabular-nums; }
.speed-toggle.on { color: var(--accent); border-color: var(--accent-line); }

/* Vollbild: die Buehne nimmt alles, die Leiste bleibt unten. */
.viewer:fullscreen { display: flex; flex-direction: column; border-radius: 0; border: 0; background: var(--stage-void); }
.viewer:fullscreen .stage { flex: 1; min-height: 0; }
.viewer:fullscreen canvas { height: 100%; max-height: none; aspect-ratio: auto; }

/* Die Sichtschalter liegen AUF der Buehne, links unten, wie das HUD der
   Einzelclip-Ansicht im Werkzeug - und in derselben Reihenfolge. */
.stage-hud {
  position: absolute;
  left: 12px;
  bottom: 12px;
  display: flex;
  flex-direction: column-reverse;
  gap: 6px;
}

.hud-toggle {
  width: 34px;
  height: 34px;
  min-height: 0;
  padding: 0;
  display: grid;
  place-items: center;
  border: 1px solid var(--on-stage-line);
  border-radius: var(--radius-sm);
  background: var(--on-stage-scrim);
  color: var(--on-stage-dim);
  backdrop-filter: blur(6px);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease, background-color 120ms ease;
}

.hud-toggle svg { width: 20px; height: 20px; }
.hud-toggle:hover { color: var(--on-stage-ink); border-color: var(--on-stage-accent-line); }
.hud-toggle[aria-pressed='true'] {
  color: var(--on-stage-accent);
  border-color: var(--on-stage-accent-line);
  background: var(--on-stage-accent-veil);
}

/* Die Proportionen liegen rechts unten - was links liegt, schaltet die
   ANSICHT um, was hier steht, aendert die FIGUR. Waagerecht, weil die vier
   nebeneinander eine Reihe zum Durchgehen sind und keine Liste von Schaltern. */
.stage-figures {
  position: absolute;
  right: 12px;
  bottom: 12px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}

/* Zwei Reihen uebereinander: oben, auf WEM der Clip laeuft, darunter die
   Masse des Mannequins. Bei einer eigenen Figur faellt die untere weg - sie
   hat ihre Proportionen. */
.stage-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
  max-width: min(62vw, 420px);
}


/* Ein Schalter mit Wort statt Zeichen: dieselbe Schale wie `.hud-toggle`, nur
   so breit, wie das Wort es braucht. */
.hud-chip {
  width: auto;
  min-width: 34px;
  padding: 0 10px;
  font-size: 12px;
  letter-spacing: 0.02em;
}

@media (max-width: 720px) {
  .viewer canvas { height: 360px; }
  .stage-hud { left: 8px; bottom: 8px; }
  .stage-figures { right: 8px; bottom: 8px; gap: 4px; }
  .stage-row { gap: 4px; max-width: 70vw; }
  .hud-chip { padding: 0 8px; font-size: 11px; }
}
.viewer-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-top: 1px solid var(--line);
  background: var(--surface);
}
.viewer-controls button { min-height: 34px; padding: 0 14px; font-size: 14px; }
/* Der Wiedergabeknopf traegt dasselbe Zeichen wie die Schalter darueber, also
   auch dieselbe Form - nur steht er in der Leiste statt auf der Buehne. */
.viewer-controls .play-toggle { flex: none; padding: 0; }
.viewer-controls .time { flex: none; min-width: 4.5em; text-align: right; font-variant-numeric: tabular-nums; }

/* Die Zeitleiste zeichnen wir selbst: der Standard-Track ist hell und liegt
   auf dunklem Grund wie ein Fremdkoerper in der Leiste. */
.viewer-controls input[type=range] {
  flex: 1;
  appearance: none;
  -webkit-appearance: none;
  height: 4px;
  min-height: 0;          /* sonst gewinnt die Mindesthoehe der Formularfelder */
  padding: 0;
  margin: 0;
  border: none;
  border-radius: var(--radius-pill);
  background: var(--line-strong);
  cursor: pointer;
}
.viewer-controls input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--accent);
  border: none;
}
.viewer-controls input[type=range]::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--accent);
  border: none;
}
.viewer-controls input[type=range]:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 4px; }
.viewer-empty { height: 480px; display: flex; align-items: center; justify-content: center; color: var(--on-stage-dim); }

dl.facts { display: grid; grid-template-columns: auto 1fr; gap: 8px 18px; margin: 18px 0; font-size: 15px; }
dl.facts dt { color: var(--text-dim); }
dl.facts dd { margin: 0; }

.actions { display: flex; flex-direction: column; gap: 10px; margin: 18px 0 0; }
.actions .button, .actions button { width: 100%; }

/* EIN DIALOG-STIL. Es gab zwei: diesen (Flaeche, gestapelte Knoepfe) und
   `dialog.sheet` (tieferer Grund, Knoepfe rechts in einer Reihe) - welcher
   kam, hing davon ab, wer den Dialog gebaut hatte. Jetzt sehen alle aus wie
   das Sheet; die Meldung auf der Clip-Seite bekommt ihre Knoepfe in einer
   Reihe, Abbrechen links. */
dialog {
  background: var(--bg-soft);
  color: var(--text);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  padding: 24px;
  width: min(480px, calc(100vw - 32px));
  box-shadow: var(--shadow), var(--highlight);
}
dialog::backdrop { background: var(--scrim); backdrop-filter: blur(3px); }
dialog .actions { flex-direction: row-reverse; justify-content: flex-start; }
dialog .actions .button, dialog .actions button { width: auto; }
dialog h2 { margin-top: 0; }

/* ── Listen ────────────────────────────────────────────────────────────── */

table.list { width: 100%; border-collapse: collapse; font-size: 15px; }
table.list th, table.list td { text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--line); vertical-align: top; }
table.list th { color: var(--text-faint); font-weight: 500; font-size: 13px; text-transform: uppercase; letter-spacing: 0.04em; }
table.list tr:hover td { background: var(--row-hover); }

.status {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.03em;
  border-radius: var(--radius-pill);
  padding: 2px 10px;
  background: var(--surface-2);
}
.status.PUBLISHED { color: var(--ok); }
.status.AUTO_HIDDEN { color: var(--warn); }
.status.REMOVED, .status.WITHDRAWN { color: var(--danger); }

.case { margin: 0 0 16px; }
.case header { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 8px; align-items: baseline; }
.case .buttons { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }

/* Starter-Clips auf der Admin-Seite: eine Zeile je Datei, mit Ergebnis. */
.starter-log { margin: 12px 0 0; padding-left: 20px; display: grid; gap: 4px; }
.starter-log:empty { display: none; }
.danger-text { color: var(--danger); }

/* Die Herkunft eines Starter-Clips, unter der Zeile mit dem Ersteller. */
.clip-source { margin: 10px 0 0; color: var(--text-dim); font-size: var(--fs-sm); }
.clip-source a { color: var(--text); }
.case input.note { width: 100%; margin-top: 10px; }

/* ── Anmeldung ─────────────────────────────────────────────────────────── */

/* Die Knoepfe der Anbieter: im Stil der Seite, nicht in den Farben der
   Anbieter - ein violettes Portal mit einem blauen, einem schwarzen und einem
   weissen Knopf darin saehe aus wie drei Werbebanner. Die Farbe steckt im
   Zeichen, und daran erkennt man sie. */
.signin-options { display: flex; flex-direction: column; gap: 10px; max-width: 360px; margin: 0 0 26px; }
.signin-option { justify-content: flex-start; gap: 12px; min-height: 46px; padding: 0 18px; }
.provider-icon { width: 20px; height: 20px; flex: none; }

/* Die Anmeldeseite selbst: eine Karte in der Mitte, dahinter derselbe
   violette Schein wie unter den Figuren. Hierher wird umgeleitet - von der
   Kontoseite ohne Sitzung, von einem abgelaufenen Link aus der Workbench -,
   also soll sie aussehen wie ein Eingang. */
.signin-page {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: clamp(24px, 7vh, 72px);
  padding-bottom: 48px;
}
.signin-page::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 420px;
  background: radial-gradient(38% 60% at 50% 0%, var(--accent-soft), transparent 70%);
  pointer-events: none;
}
.signin-card {
  position: relative;
  width: 100%;
  max-width: 440px;
  padding: 34px 32px 26px;
  text-align: center;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--highlight), var(--shadow);
}
.signin-mark { display: block; margin: 0 auto 18px; }
:root[data-theme="light"] .signin-mark { content: url("brand/aw-mark-tinte.svg"); }
.signin-card h1 { margin: 0 0 6px; }
.signin-card h1::after { content: none; }
.signin-lead { color: var(--text-dim); margin: 0 0 22px; }
.signin-card .notice { text-align: left; margin: 0 0 18px; }
.signin-card .signin-options { max-width: none; margin: 0 0 22px; }
.signin-card .signin-option { justify-content: center; }
.signin-note { font-size: 13px; color: var(--text-dim); margin: 0 0 10px; }
.signin-note.faint { color: var(--text-faint); margin-bottom: 0; }
@media (max-width: 520px) {
  .signin-card { padding: 26px 18px 20px; border-radius: var(--radius); }
}

/* Die Rueckkehr vom Anbieter springt hierher (#sign-ins) - ohne Abstand
   laege die Ueberschrift unter dem festen Seitenkopf. */
#sign-ins { scroll-margin-top: 110px; }
.signin-list { list-style: none; padding: 0; margin: 0 0 8px; max-width: 620px; }
.signin-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--line);
}
.signin-row-text { flex: 1; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; min-width: 0; }
.signin-row .chip { padding: 1px 9px; font-size: 12px; }
.signin-row button { flex: none; }

.code-display {
  font: 700 38px/1.2 ui-monospace, "Cascadia Mono", Consolas, monospace;
  letter-spacing: 0.12em;
  text-align: center;
  margin: 18px 0;
  padding: 18px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.prose { max-width: 760px; }
.prose h2 { margin-top: 34px; }
.prose li { margin: 6px 0; }
.todo {
  border: 1px dashed color-mix(in srgb, var(--warn) 45%, transparent);
  background: color-mix(in srgb, var(--warn) 7%, transparent);
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  color: var(--warn);
  margin: 12px 0;
  font-size: 14px;
}

/* Hier stand bis hierher ein Rest aus der Zeit der SEITENLEISTE: ein
   Grid-Raster fuer `body` (der laengst `flex` ist), eine Kopfzeile, die sich
   von senkrecht auf waagerecht drehte, und Regeln fuer `.sidebar-hint` und
   `.sidebar-foot` - Klassen, die es seit dem Umzug der Navigation nach oben
   nicht mehr gibt. Wirksam war davon nur zweierlei: ein zweiter Innenabstand
   am Kopf (neben dem des Bands) und `overflow-x: auto`, das aus dem Kopf bei
   Bedarf einen Schiebestreifen machte. Beides ist weg; wie der Kopf schmal
   wird, sagen die Bloecke bei 1080 und 620 Punkten. */
@media (max-width: 900px) {
  main { padding: 26px 18px 56px; }
  .site-footer { padding: 20px 18px; justify-content: center; }
  h1 { font-size: 30px; }
}

/*  Die Build-Marke steht im Fuss ganz rechts und soll dort nicht mitreden:
    kleiner, blasser, und bei schmalen Fenstern faellt sie in die naechste
    Zeile wie die Links daneben. */
.site-footer .build {
  margin-left: auto;
  color: var(--text-faint);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

/* ── Knopfreihe der Fehlerseite ────────────────────────────────────────
   Hier stand die Startseite: Kopf, Zahlen, zeitweise eine Figur, Reihen mit
   Clips und Sammlungen, drei Schritte. Seit 2026-09-24 ist der Katalog selbst
   die Startseite, wie der Reiter "Animations" bei Mixamo. Uebrig ist nur die
   Knopfreihe, die die Fehlerseite mitbenutzt. */

.hero-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.hero-actions .button { padding: 11px 20px; }

/* ── Zeichen, Tooltips, Icon-Knoepfe ───────────────────────────────────
   Weniger Wort, mehr Zeichen - und dafuer traegt JEDES Zeichen seinen Satz
   mit sich. `data-tip` legt ihn beim Hovern und beim Tastaturfokus darueber;
   derselbe Satz steht als `aria-label` am Knopf, damit ein Screenreader ihn
   vorliest statt "Schaltflaeche".

   Der Tooltip ist ein ::after am Element selbst. Das geht, weil kein Element
   mit `data-tip` sein ::after schon anderweitig benutzt - die Kartentitel tun
   das (sie decken damit die ganze Karte als Klickflaeche ab) und tragen
   deshalb keines.
---------------------------------------------------------------------------- */

.icon { width: 18px; height: 18px; flex: none; display: block; }
.icon.filled { fill: currentColor; }

/* Die Beta-Marke im Kopf: klein, aber auf jeder Seite. */
.beta-mark {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

[data-tip] { position: relative; }

[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 9px);
  left: 50%;
  transform: translateX(-50%) translateY(3px);
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 5px 9px;
  font-size: 12.5px;
  line-height: 1.3;
  font-weight: 500;
  white-space: nowrap;
  box-shadow: var(--shadow);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease;
  z-index: 60;
}

[data-tip]:hover::after,
[data-tip]:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%);
}

/* Am oberen Rand kippt er nach unten - sonst steht er ausserhalb des Bildes. */
[data-tip-below]::after { bottom: auto; top: calc(100% + 9px); }

/* Am Seitenrand haengt er nach innen statt mittig (app.js setzt das Attribut
   beim Hinzeigen) - sonst schnitte der Rand ihn ab. */
[data-tip-edge="end"]::after { left: auto; right: 0; transform: translateY(3px); }
[data-tip-edge="start"]::after { left: 0; transform: translateY(3px); }
[data-tip-edge]:hover::after, [data-tip-edge]:focus-visible::after { transform: none; }

/* Wer gerade einen Kasten geoeffnet hat, braucht keinen Zettel darueber. */
[data-tip].tip-off::after { content: none; }

/* Ein Knopf, der aus einem Zeichen besteht - mit seiner Zahl, wenn es eine gibt. */
.icon-action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0 10px;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.icon-action:hover { background: var(--surface-2); color: var(--text); border-color: var(--line); text-decoration: none; }
.icon-action:disabled { opacity: 0.55; cursor: default; }
.icon-action:active { transform: none; }
.icon-action .count { line-height: 1; }

/* Gesetzt heisst gefuellt: das Herz rot, der Stern in der Akzentfarbe. */
.icon-action.on { color: var(--accent); }
.icon-action.like.on { color: var(--danger); }
.icon-action.danger { color: var(--danger); }
.icon-action.danger:hover { background: var(--danger-soft); border-color: var(--danger-line); }

/* In einer Aktionszeile tragen dieselben Knoepfe eine Kante - dort stehen sie
   allein und muessen ohne Nachbarn als Knopf erkennbar sein. */
.clip-actions .icon-action,
.profile-actions .icon-action,
.collection-actions .icon-action {
  border-color: var(--line);
  background: var(--surface);
  min-height: 36px;
  padding: 0 13px;
}
.clip-actions .icon-action:hover,
.profile-actions .icon-action:hover,
.collection-actions .icon-action:hover { border-color: var(--line-strong); }
.clip-actions .icon-action.on,
.profile-actions .icon-action.on { background: var(--accent-soft); border-color: var(--accent-line); }
.clip-actions .icon-action.like.on { background: var(--danger-soft); border-color: var(--danger-line); }

/* ── Karte: Autor links, Handgriffe rechts ────────────────────────────── */

.card-actions { display: flex; align-items: center; gap: 2px; position: relative; z-index: 1; }
.card-actions .icon-action { padding: 0 8px; min-height: 30px; }

/* ── Ein Kasten, der an einem Knopf haengt ────────────────────────────── */

.popover {
  position: absolute;
  z-index: 80;
  min-width: 268px;
  max-width: 320px;
  background: var(--bg-soft);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 8px;
}

.popover-note { display: flex; flex-direction: column; gap: 10px; padding: 6px; }
.popover-note p { margin: 0; color: var(--text-dim); font-size: 13.5px; }

.picker { display: flex; flex-direction: column; gap: 6px; }

.picker-search {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-faint);
}
.picker-search input {
  flex: 1;
  border: 0;
  background: transparent;
  color: var(--text);
  padding: 8px 0;
  margin: 0;
  font-size: 14px;
  min-width: 0;
}
.picker-search input:focus { outline: none; }
.picker-search:focus-within { border-color: var(--accent-line); }

.picker-list { display: flex; flex-direction: column; gap: 2px; max-height: 232px; overflow: auto; }
.picker-list p { margin: 0; padding: 10px; }

.picker-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 36px;
  padding: 8px 10px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-dim);
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.picker-row:hover { background: var(--surface); color: var(--text); }
.picker-row.on { color: var(--accent); }
.picker-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.picker-new {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.picker-new:hover { background: var(--surface); }

/* ── Der Dialog fuer eine Sammlung ────────────────────────────────────── */

dialog.sheet { width: min(560px, calc(100vw - 32px)); }
dialog.sheet h2 { margin: 0 0 18px; font-size: 20px; }
dialog.sheet h2::after { content: none; }
dialog.sheet .field { display: block; margin-bottom: 16px; }
dialog.sheet .counter { float: right; }
/* Der Text einer Rueckfrage (AW.confirmDialog) steht zwischen Titel und Knoepfen. */
dialog.sheet form > p { margin: 0 0 12px; line-height: 1.55; }
dialog.sheet form > p:last-of-type { margin-bottom: 20px; }

.choices { border: 0; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.choices legend { padding: 0 0 8px; color: var(--text-dim); font-size: 13.5px; }
.choices label { display: flex; align-items: center; gap: 10px; font-size: 14px; color: var(--text-dim); }
.choices input[type="radio"] { margin: 0; width: 16px; height: 16px; accent-color: var(--accent); flex: none; }
.choices strong { color: var(--text); font-weight: 600; }

.dialog-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 4px; }

/* Ein Nebensatz im Dialog: der Weg woanders hin, abgesetzt von dem, was der
   Dialog selbst tut. */
.dialog-aside {
  margin: 0 0 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  line-height: 1.5;
}

/* ── Das Profil ────────────────────────────────────────────────────────
   Kopf, Zahlen, Reiter - in dieser Reihenfolge: erst WER das ist, dann WIE
   VIEL, dann die Sachen selbst.
---------------------------------------------------------------------------- */

.profile-head {
  display: flex;
  align-items: flex-start;
  gap: 22px;
  padding: 8px 0 24px;
  flex-wrap: wrap;
}

.profile-avatar {
  width: 88px;
  height: 88px;
  border-radius: 50%;
  flex: none;
  object-fit: cover;
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 34px;
  font-weight: 700;
  color: var(--accent);
}

.profile-identity { flex: 1 1 320px; min-width: 0; }
.profile-identity h1 { font-size: 30px; margin: 0 0 2px; }
.profile-identity h1::after { content: none; }
.profile-handle { color: var(--text-faint); font-size: 14px; }
.profile-bio { color: var(--text-dim); margin: 10px 0 0; max-width: 62ch; white-space: pre-wrap; }

.profile-role {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 10px;
  padding: 2px 9px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 12px;
  font-weight: 600;
  vertical-align: middle;
}

.profile-numbers { display: flex; flex-wrap: wrap; gap: 8px 22px; margin: 14px 0 0; color: var(--text-dim); font-size: 13.5px; }
.profile-numbers span { display: inline-flex; align-items: center; gap: 7px; }
.profile-numbers b { color: var(--text); font-weight: 650; font-variant-numeric: tabular-nums; }
.profile-numbers .icon { width: 16px; height: 16px; color: var(--text-faint); }

.profile-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.profile-tabs { margin: 0 0 24px; }

/* Die Auszeichnungen: eine Wand aus Zeichen, jedes mit seinem Satz im
   Tooltip. Was noch offen ist, steht blass daneben - aber nur auf dem
   eigenen Profil, sonst waere es eine fremde Aufgabenliste. */
.awards { display: flex; flex-wrap: wrap; gap: 12px; }

.award {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 232px;
  padding: 12px 16px 12px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.award .icon { width: 26px; height: 26px; color: var(--accent); }
.award.locked { opacity: 0.45; }
.award.locked .icon { color: var(--text-faint); }
.award-name { font-weight: 600; font-size: 14.5px; }
.award-sub { color: var(--text-faint); font-size: 12.5px; }
.award-tier { color: var(--accent); font-size: 12px; font-weight: 700; letter-spacing: 0.04em; }

/* ── Sammlungen ───────────────────────────────────────────────────────── */

.collection-head { display: flex; align-items: flex-start; gap: 18px; flex-wrap: wrap; margin-bottom: 22px; }
.collection-head h1 { margin: 0 0 6px; font-size: 30px; }
.collection-head h1::after { content: none; }
.collection-copy { flex: 1 1 420px; min-width: 0; }
.collection-copy p { margin: 8px 0 0; color: var(--text-dim); max-width: 70ch; white-space: pre-wrap; }
.collection-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.collection-card .card-duration { background: var(--on-stage-scrim-strong); }

@media (max-width: 720px) {
  .profile-head { gap: 16px; }
  .profile-avatar { width: 64px; height: 64px; font-size: 26px; }
  .profile-identity h1 { font-size: 24px; }
  .award { min-width: 100%; }
}

/* ── Die eigenen Figuren ──────────────────────────────────────────────────
   Die Seite, auf der sie leben. Die Schalterreihe an der Buehne waehlt nur
   aus; hinzufuegen, nachsehen und loswerden passiert hier. */
.figure-drop {
  margin: 22px 0 18px;
  padding: 26px 20px;
  border: 2px dashed var(--line-strong);
  border-radius: var(--radius);
  text-align: center;
  transition: border-color 140ms ease, background-color 140ms ease;
}
.figure-drop p { margin: 0 0 6px; }
.figure-drop .button { margin-top: 10px; }
.figure-drop.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }

.figure-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px;
  margin: 18px 0 34px;
}

.figure-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}
.figure-card.active { border-color: var(--accent-line); }

/* Ein Standbild, kein zweiter Viewer: wer die Figur in Bewegung sehen will,
   schickt einen Clip darauf. */
.figure-shot {
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  display: block;
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 10%, transparent), transparent 70%);
}

.figure-body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 4px; }
.figure-body h3 { margin: 0; font-size: 15px; }
.figure-body p { margin: 0; }

.figure-actions { display: flex; gap: 8px; margin-top: 10px; }
.figure-actions .button { flex: 1; min-height: 32px; padding: 0 10px; font-size: 13px; }

.figure-empty {
  grid-column: 1 / -1;
  padding: 28px 20px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  text-align: center;
}
.figure-empty p { margin: 0 0 4px; }

.figure-how { margin-top: 30px; }

/* Eine geratene Zuordnung ist ein Vorschlag, und ein Vorschlag darf nicht
   aussehen wie eine Tatsache. Gelb: angesehen werden. Rot: geht so nicht. */
.figure-card.figure-unsure { border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.figure-card.figure-broken { border-color: color-mix(in srgb, var(--danger) 50%, transparent); }

.figure-flag {
  margin-top: 6px;
  padding-left: 9px;
  border-left: 2px solid var(--warn);
  color: var(--text-dim);
  font-size: 12.5px;
  line-height: 1.45;
}
.figure-flag.bad { border-left-color: var(--danger); }

/* ── Welcher Knochen welcher ist ──────────────────────────────────────────
   Die Maske zu einer geratenen Zuordnung. Sie kann 55 Zeilen lang werden,
   also darf sie scrollen - und Finger und Gesicht liegen zugeklappt, weil
   dort fast nie etwas zu korrigieren ist. */
dialog.bone-sheet { width: min(620px, calc(100vw - 32px)); }
dialog.bone-sheet form { display: flex; flex-direction: column; max-height: min(78vh, 760px); }
dialog.bone-sheet > form > .notice { margin: 14px 0 6px; flex: none; }
dialog.bone-sheet .dialog-actions {
  flex: none;
  padding-top: 14px;
  margin-top: 10px;
  border-top: 1px solid var(--line);
}

.bone-group {
  flex: none;
  padding: 12px 0 4px;
  border-top: 1px solid var(--line);
}
.bone-group:first-of-type { border-top: 0; }
.bone-group h3 { margin: 0 0 8px; font-size: 13px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-dim); }
.bone-group summary { cursor: pointer; font-size: 13px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-dim); }
.bone-group summary::marker { color: var(--text-dim); }

/* Der scrollende Teil ist die Liste, nicht der Dialog: Kopfzeile, Zaehlung
   und die Knoepfe sollen stehen bleiben, waehrend man 55 Zeilen durchgeht. */
dialog.bone-sheet > form { overflow: hidden; }
dialog.bone-sheet .bone-scroll { overflow-y: auto; flex: 1 1 auto; padding-right: 4px; }

.bone-row {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) minmax(0, 1.4fr);
  align-items: center;
  gap: 10px;
  padding: 3px 8px;
  margin: 0 -8px;
  border-radius: var(--radius-sm);
}
.bone-name { font-size: 13.5px; color: var(--text-dim); }
.bone-must { color: var(--accent); margin-left: 3px; }
.bone-pick { width: 100%; min-height: 30px; font-size: 13px; }

.bone-row.was-guessed .bone-name { color: var(--text); }
.bone-row.bone-gap { background: color-mix(in srgb, var(--danger) 10%, transparent); }
.bone-row.bone-gap .bone-pick { border-color: color-mix(in srgb, var(--danger) 55%, transparent); }
.bone-row.bone-clash { background: color-mix(in srgb, var(--warn) 10%, transparent); }
.bone-row.bone-clash .bone-pick { border-color: color-mix(in srgb, var(--warn) 55%, transparent); }

/* ── Bewegung ──────────────────────────────────────────────────────────── */
/* Alles hier ist Zugabe: nimmt man den Abschnitt heraus, funktioniert jede
   Seite genauso, nur ohne Uebergaenge. Die Regel dafuer: Bewegung sagt, was
   gerade passiert ist - etwas kam an, etwas wurde gesetzt, etwas ging -, und
   sie ist vorbei, bevor man darauf wartet. Keine Endlosschleifen ausser dem
   Schimmer, solange etwas wirklich laedt. */

@keyframes aw-rise {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
@keyframes aw-rise-small {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}
@keyframes aw-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes aw-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.28); }
  100% { transform: scale(1); }
}
@keyframes aw-sheen {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}
@keyframes aw-dialog-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to { opacity: 1; transform: none; }
}

/* Karten kommen gestaffelt, je 35 ms spaeter - ab der zwoelften alle
   zugleich, wer 24 Karten laedt, soll nicht zusehen muessen. `backwards`,
   nicht `both`: ein stehengebliebenes Endbild (`transform: none`) schlaege
   sonst das Anheben beim Hovern. */
.grid > .card { animation: aw-rise var(--dur-slow) var(--ease-out) backwards; }
.grid > .card:nth-child(2) { animation-delay: 35ms; }
.grid > .card:nth-child(3) { animation-delay: 70ms; }
.grid > .card:nth-child(4) { animation-delay: 105ms; }
.grid > .card:nth-child(5) { animation-delay: 140ms; }
.grid > .card:nth-child(6) { animation-delay: 175ms; }
.grid > .card:nth-child(7) { animation-delay: 210ms; }
.grid > .card:nth-child(8) { animation-delay: 245ms; }
.grid > .card:nth-child(9) { animation-delay: 280ms; }
.grid > .card:nth-child(10) { animation-delay: 315ms; }
.grid > .card:nth-child(11) { animation-delay: 350ms; }
.grid > .card:nth-child(12) { animation-delay: 385ms; }

/* Die Vorschau blendet ein, sobald ihr erstes Bild steht (`is-drawn` setzen
   card-stage.js und viewer.js). Darunter liegt derselbe Verlauf, den die
   Leinwand sonst selbst traegt - so blitzt beim Einblenden nichts auf. Solange
   sie laedt, zieht ein Schimmer darueber. */
.card-stage { background: radial-gradient(120% 90% at 50% 20%, #1e1c28 0%, #100f15 70%); overflow: hidden; }
.card canvas.fade-in { opacity: 0; transition: opacity var(--dur-slow) var(--ease-out); }
.card canvas.fade-in.is-drawn { opacity: 1; }
.card-stage:has(> canvas.fade-in:not(.is-drawn))::after,
.card.placeholder .card-stage::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, 0.045) 50%, transparent 70%);
  animation: aw-sheen 1.5s var(--ease-in-out) infinite;
}

/* Platzhalter, solange eine Wand laedt (AW.placeholderCards): dieselbe Form
   wie eine Karte, damit nichts springt, wenn die echten kommen. */
.card.placeholder { pointer-events: none; }
.card.placeholder .card-stage { height: 206px; }
.card.placeholder .ph-line { display: block; height: 12px; width: 68%; border-radius: 6px; background: var(--surface-2); }
.card.placeholder .ph-line.short { width: 38%; margin-top: 6px; }

/* Was erst nach dem Laden sichtbar wird, taucht auf, statt hineinzuspringen. */
#clip:not(.hidden), #collection:not(.hidden), #profile:not(.hidden) {
  animation: aw-fade var(--dur-slow) var(--ease-out) backwards;
}

/* Dialoge, Kaesten und Meldungen gleiten ein. */
dialog[open] { animation: aw-dialog-in var(--dur) var(--ease-out) backwards; }
dialog[open]::backdrop { animation: aw-fade var(--dur) var(--ease-out) backwards; }
.popover { animation: aw-rise-small var(--dur) var(--ease-out) backwards; }
.toast {
  animation: aw-rise var(--dur) var(--ease-out) backwards;
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.toast.leaving { transform: translateY(6px); }

/* Herz, Stern, Folgen: ein kurzer Puls, wenn etwas gesetzt wird. */
.icon-action.pulse .icon { animation: aw-pop 340ms var(--ease-out); }

/* SEITENWECHSEL. Das Portal besteht aus echten Seiten, und seit es sie gibt,
   koennen Browser zwischen zwei Seiten derselben Adresse ueberblenden - ohne
   eine Zeile Skript. Der Kopf traegt einen eigenen Namen und bleibt deshalb
   stehen, statt mitzublenden. Wer es nicht kann, laedt wie bisher. */
@view-transition { navigation: auto; }
.site-header { view-transition-name: site-header; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: var(--dur); animation-timing-function: var(--ease-out); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  @view-transition { navigation: none; }
}
