/* ============================================================
   Komponente: spinner · skelett (Ladezustände)
   ------------------------------------------------------------
   Quelle: SKILL.md §23, Figma „Error & Success states" →
   loading spinner animation (vier Frames, zwei Größen).
   Freigegeben am 28.08.2026 — vorher Entwurf im CSS von
   examples/motion-demo.html.

   Setzt tokens.css voraus. Die Bewegung — Drehung, Bogenlänge,
   Schimmer, Reduced Motion — steht in components/motion.css.
   Diese Datei setzt nur Form und Farbe.

   ZWEI DINGE IN EINER DATEI, weil es eine Entscheidung ist: wie
   zeigen wir, dass etwas lädt.
     · spinner  — die Dauer ist unbekannt
     · skelett  — die FORM des Kommenden ist bekannt
   Wenn du das getrennt haben willst, sag es; motion.css zielt
   auf beide.

   BEIDE ERSCHEINEN ERST NACH EINER WARTEZEIT (~300 ms). Der
   Figma-Frame trägt die Notiz „Nach Verzögerung". Ein kurz
   aufblitzender Spinner lässt eine schnelle Antwort langsam
   aussehen. Die Verzögerung gehört in die Logik, nicht ins CSS —
   dieselbe Regel wie §23.4.

   VERWENDUNG
     <svg class="spinner" viewBox="0 0 28 28" role="img" aria-label="Lädt">
       <circle class="spinner__bahn" cx="14" cy="14" r="12"></circle>
       <circle class="spinner__bogen" cx="14" cy="14" r="12"></circle>
     </svg>

     <svg class="spinner spinner--klein" viewBox="0 0 28 28" aria-hidden="true">…</svg>

   Der große Spinner steht allein und braucht ein aria-label. Der
   kleine sitzt neben Text, der schon sagt, was passiert — dort
   aria-hidden, sonst hört der Screenreader es zweimal.

     <div class="skelett skelett--karte"></div>
     <div class="skelett skelett--80"></div>

   Skelette sind reine Flächen: aria-hidden am Container, und die
   Auskunft „lädt" gehört an den Bereich, nicht an jeden Balken.
   ============================================================ */

/* ------------------------------------------------------------
   Spinner
   ------------------------------------------------------------
   Aufbau nach der Figma-Animation: die Bahn ist ein VOLLER Ring,
   darauf liegt ein Bogen, der beim Drehen wächst und wieder
   schrumpft.

   GEOMETRIE 1:1 AUS FIGMA, am 28.08.2026 an der Komponente
   nachgemessen (`loading spinner animation`):

     Größe small   Frame 28 · Ellipse 24 · Strich 4 · Align center
     Größe large   Frame 58 · Ellipse 50 · Strich 8 · Align center

   Der Strich liegt MITTIG auf dem Pfad, deshalb ist der Frame
   genau Pfaddurchmesser + Strichstärke: 24 + 4 = 28, 50 + 8 = 58.
   Verhältnis Strich zu Pfad: 1 : 6.

   Daraus der viewBox 0 0 28 28 mit r = 12 und stroke-width 4 —
   das ist die small-Größe unskaliert. Für large genügt die
   Darstellungsgröße 58: 58/28 × 4 = 8,3 und 58/28 × 24 = 49,7,
   also Figmas 8 und 50. Eine Geometrie, zwei Größen, beide
   deckungsgleich mit der Komponente.

   FRÜHER STAND HIER 44 MIT r = 18 UND STRICH 5 (Verhältnis
   1 : 7,2). Das kam aus dem Entwurf in motion-demo.html und hatte
   keine Entsprechung in Figma — der gebaute Spinner war dünner
   als der gezeichnete. Korrigiert am 28.08.2026.
   ------------------------------------------------------------ */

.spinner {
  width: 58px;
  height: 58px;
}

.spinner--klein {
  width: 28px;
  height: 28px;
}

.spinner__bahn,
.spinner__bogen {
  fill: none;
  stroke-width: 4;
}

/* Die Bahn ist ein geschlossener Ring und braucht keine Kappen —
   in Figma steht sie auf strokeCap NONE. Der Bogen hat zwei
   sichtbare Enden und rundet sie (ROUND). */
.spinner__bogen { stroke-linecap: round; }

/* Die Bahn ist Fläche, kein Signal — sie darf leise sein.
   Der Bogen trägt die Auskunft. */
.spinner__bahn  { stroke: var(--label-outline); }
.spinner__bogen { stroke: var(--text-accent); }

/* ------------------------------------------------------------
   Die Bahn IN einer Komponente
   ------------------------------------------------------------
   Freistehend liegt der Spinner auf surface-primary, und die Bahn
   kann ein festes Grau sein — label-outline oben.

   In einer Komponente geht das nicht: die Fläche wechselt je
   Familie und je Mode, ein festes Grau wäre auf der einen
   unsichtbar und auf der anderen zu laut. Dort nimmt die Bahn
   deshalb dieselbe Farbe wie der Bogen, nur auf 30 % Deckkraft —
   siehe button.css, .btn__spinner.

   Die Rollentrennung bleibt in beiden Fällen dieselbe: der Bogen
   trägt die Auskunft, die Bahn gibt ihm einen Weg.
   ------------------------------------------------------------ */

/* ------------------------------------------------------------
   Skelett
   ------------------------------------------------------------
   Nur wo die Form des Kommenden bekannt ist — eine Karte, drei
   Textzeilen. Wo sie unbekannt ist, ist der Spinner ehrlicher:
   ein Skelett, das nicht zum Ergebnis passt, erzeugt einen
   Sprung beim Einsetzen.

   DAS SKELETT IST EINE VERTIEFUNG, KEINE ERHEBUNG.
   Deshalb label-fill-inverted und nicht label-fill. Ein Skelett
   ist ein Loch, das gefüllt wird — es liegt nicht vor seiner
   Umgebung, sondern darin.

   Korrigiert am 28.08.2026. Vorher stand hier label-fill, und
   das ist derselbe Wert wie surface-card: das Skelett war
   INNERHALB einer Karte auf 1,00:1 unsichtbar, in beiden Modes.
   Und weil der Schimmer bei prefers-reduced-motion wegfällt,
   blieb dann gar nichts übrig.

   Als Vertiefung: 1,13:1 in Light, 1,23:1 in Dark gegen die
   Kartenfläche — dieselbe leise Stufe wie Elevation, nur nach
   unten (SKILL.md §2.1).

   DARAUS FOLGT EINE PLATZIERUNGSREGEL: Skelette sitzen INNERHALB
   der Fläche, deren Inhalt sie ersetzen — in einer Karte, einem
   Sheet, einem Dialog. Direkt auf surface-primary wären sie
   wieder unsichtbar, weil die Vertiefung dort der Grund selbst
   ist. Wer eine ganze Karte skelettiert, nimmt die Karte mit
   ihrem Rand und legt die Balken hinein.

   Der Schimmer ist Verstärkung, nicht Signal — bei
   prefers-reduced-motion fällt er weg (motion.css), die Fläche
   trägt dann allein.
   ------------------------------------------------------------ */

.skelett {
  position: relative;
  overflow: hidden;
  height: 16px;
  border-radius: var(--radius-sm);
  background-color: var(--label-fill-inverted);
}

.skelett + .skelett {
  margin-top: var(--space-sm);
}

.skelett::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent,
    var(--transparent-gray-10),
    transparent
  );
  transform: translateX(-100%);
}

/* Maße für die üblichen Fälle. Weitere Breiten gehören an den
   Screen, nicht in diese Datei — sonst wächst hier eine
   Utility-Sammlung. */
.skelett--karte { height: 96px; }
.skelett--80    { width: 80%; }
.skelett--60    { width: 60%; }
