/* loading.css — die drei Ladezustaende als reine Klassen. Kein Platzhalter-Markup,
   das mit dem echten Layout synchron gehalten werden muesste; das JS togglet nur
   eine Klasse, das CSS macht den Rest.

   Farb-Token als CSS-Variablen, damit Hell/Dunkel EINE Stelle ist. Der
   Dunkelschalter dieses Stacks ist data-bs-theme (Tabler/Bootstrap), nicht nur
   die OS-Preference - deshalb der Attribut-Selektor, nicht @media. */
:root                  { --skel-base: rgba(0,0,0,.07);     --skel-hi: rgba(0,0,0,.14); }
[data-bs-theme="dark"] { --skel-base: rgba(255,255,255,.07); --skel-hi: rgba(255,255,255,.16); }

/* --- 1. Skeleton: erstes Laden einer Ansicht mit bekanntem Layout ------------
   Inhalt unsichtbar (visibility, NICHT display:none - die Hoehe bleibt, sonst
   springt das Layout beim Eintreffen der Daten). Ein grauer Block je Karte, ueber
   den ein hellerer Streifen wandert. */
.is-loading .skel { position: relative; }
.is-loading .skel > * { visibility: hidden; }
.is-loading .skel::after {
  content: ""; position: absolute; inset: .5rem;
  border-radius: 4px;
  background: linear-gradient(90deg, var(--skel-base) 25%, var(--skel-hi) 50%, var(--skel-base) 75%);
  background-size: 220% 100%;
  animation: skel-shimmer 1.4s linear infinite;
}
@keyframes skel-shimmer { from { background-position: 120% 0; } to { background-position: -20% 0; } }

/* --- 2. Dezenter Kopf-Spinner: NUR mit belegtem Grund -----------------------
   Der Default fuers Nachladen ist der globale Busy-Overlay (unten, Prinzip 1:
   ein Spinner, kein lokaler pro View). Dieses Muster nur, wenn die uebrige
   Oberflaeche waehrend des Ladens bedienbar bleiben MUSS - dann dreht sich das
   vorhandene Kopfzeilen-Icon. Achtung: by design leicht zu uebersehen. */
.is-reloading .reload-icon { animation: reload-spin .75s linear infinite; transform-origin: 50% 50%; }
@keyframes reload-spin { to { transform: rotate(360deg); } }

/* --- 3. Globaler Busy-Overlay: blockierende AKTION (Speichern, Zahlung) ------
   Voll-Viewport am body, faengt Klicks. Groesse/Abdeckung: BUSY-SPINNER.md. */
body.is-busy::before {
  content: ""; position: fixed; inset: 0;
  background: rgba(255,255,255,.6); z-index: 2000;
  pointer-events: auto;   /* der Backdrop ist die Sperre - er faengt die Klicks */
}
[data-bs-theme="dark"] body.is-busy::before { background: rgba(24,36,51,.6); }
body.is-busy::after {
  content: ""; position: fixed; top: 50%; left: 50%;
  width: 2.5rem; height: 2.5rem; margin: -1.25rem 0 0 -1.25rem;
  /* Farb-TOKEN, nicht currentColor: das ::after erbt die Textfarbe des body -
     auf einer dunklen Seite wird der Spinner damit fast unsichtbar. Das Token
     hat eine Notfarbe, falls es im Projekt nicht definiert ist. */
  border: .25em solid var(--busy-spinner, #6c757d); border-right-color: transparent;
  border-radius: 50%;
  animation: busy-spin .75s linear infinite; z-index: 2001;
  /* Der Spinner selbst faengt KEINE Klicks - das macht der Backdrop (::before).
     Sonst schluckt ausgerechnet die Mitte des Bildschirms Ereignisse, auch
     wenn der Backdrop einmal fehlt. */
  pointer-events: none;
}
@keyframes busy-spin { to { transform: rotate(360deg); } }

/* Bewegung reduzieren (WCAG 2.3.3): der Ladezustand bleibt ohne Animation
   erkennbar - Skeleton als stehender Block, Spinner langsamer statt hektisch. */
@media (prefers-reduced-motion: reduce) {
  .is-loading .skel::after { animation: none; background: var(--skel-base); }
  .is-reloading .reload-icon { animation: none; }
  body.is-busy::after { animation-duration: 2s; }
}
