/* ==========================================================================
   YoruVerse loading state — Shell-native.
   Replaces the full-screen #loadingScreen overlay with:
     1. .yv-progress  — a 2px indeterminate line at the top of the viewport
     2. .yv-skeleton  — neutral content-shaped placeholders inside the real shell
     3. .yv-loading-error — a readable failure state with a Retry button
   No purple, no gradients, no blur, no spinner. Two cheap keyframes only.
   Everything resolves to the existing --ss-* scale (with safe fallbacks for
   pages that do not load series-shell.css).
   ========================================================================== */

:root {
  --yv-skel-fill: var(--ss-surface-2, var(--bg-tertiary, #1f2937));
  --yv-skel-line: var(--ss-border, var(--border-color, #262b33));
  --yv-skel-text: var(--ss-text, var(--text-primary, #f9fafb));
  --yv-skel-muted: var(--ss-text-muted, var(--text-secondary, #9ca3af));
  --yv-skel-shimmer: rgba(255, 255, 255, 0.04);
}

[data-theme="light"] {
  --yv-skel-shimmer: rgba(0, 0, 0, 0.03);
}

/* --- 1. progress line ---------------------------------------------------- */
.yv-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 100;
  overflow: hidden;
  pointer-events: none;
  background: transparent;
}

.yv-progress::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 34%;
  border-radius: 999px;
  background: var(--yv-skel-text);
  opacity: 0.9;
  animation: yvProgress 900ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

@keyframes yvProgress {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(394%); }
}

/* --- 2. skeleton --------------------------------------------------------- */
/* While the skeleton is up it stands in for the shell's own content, so the
   frame keeps its geometry and the swap happens in the same boxes. */
.yv-loading-active > :not(.yv-skeleton):not([class*="-identity"]):not([class*="-controlzone"]):not([data-yv-keep]) {
  display: none !important;
}

.yv-skeleton {
  display: block;
  width: 100%;
  padding: 8px 0 24px;
}

.yv-skeleton .yv-skel-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--yv-skel-line);
}

.yv-skeleton .yv-skel-col {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
  min-width: 0;
}

.yv-skeleton .yv-skel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 16px;
}

.yv-skeleton .yv-skel-tile {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.yv-skeleton .yv-skel-detail {
  display: flex;
  gap: 24px;
  padding: 24px 0;
  border-bottom: 1px solid var(--yv-skel-line);
  margin-bottom: 16px;
}

.yv-skeleton .yv-skel-panel {
  border: 1px solid var(--yv-skel-line);
  border-radius: 8px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 16px;
}

.yv-skeleton .yv-skel-reader {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
}

.yv-skel-line,
.yv-skel-block {
  position: relative;
  overflow: hidden;
  background-color: var(--yv-skel-fill);
  background-image: linear-gradient(
    90deg,
    transparent 0%,
    var(--yv-skel-shimmer) 50%,
    transparent 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: yvShimmer 1.4s linear infinite;
}

.yv-skel-line {
  height: 14px;
  border-radius: 6px;
  width: 100%;
}

.yv-skel-line[data-w="80"] { width: 80%; }
.yv-skel-line[data-w="60"] { width: 60%; }
.yv-skel-line[data-w="40"] { width: 40%; }
.yv-skel-line[data-w="25"] { width: 25%; }
.yv-skel-line.is-meta { height: 13px; opacity: 0.75; }

.yv-skel-block {
  border-radius: 8px;
  width: 48px;
  height: 64px;
  flex: 0 0 auto;
}

@keyframes yvShimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* --- 3. error state ------------------------------------------------------ */
.yv-loading-error {
  border: 1px solid var(--yv-skel-line);
  border-radius: 8px;
  padding: 32px 16px;
  text-align: center;
  color: var(--yv-skel-muted);
  font-size: 0.95rem;
  margin: 24px 0;
}

.yv-loading-error p {
  margin: 0 0 16px;
  color: var(--yv-skel-muted);
}

.yv-loading-error button {
  border: 1px solid var(--yv-skel-line);
  background: transparent;
  color: var(--yv-skel-text);
  border-radius: 8px;
  padding: 8px 16px;
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.yv-loading-error button:hover {
  background: var(--yv-skel-fill);
}

/* Host used on pages whose real content container is hidden until data lands. */
.yv-loading-host {
  display: block;
  width: 100%;
  max-width: var(--ss-max, 1120px);
  margin: 0 auto;
  padding: 0 16px 48px;
}

/* --- 4. legacy shim ------------------------------------------------------
   One release only: any page still shipping the old overlay degrades to
   "no loader" instead of "permanent full-screen curtain". */
.loading-screen {
  display: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .yv-progress::after,
  .yv-skel-line,
  .yv-skel-block {
    animation: none !important;
  }
}
