/* ═══════════════════════════════════════════════════════════════════
   SITU · Feedback · spinner / skeleton / progress / retry / banner
   ───────────────────────────────────────────────────────────────────
   配套 vendor/situ-feedback.js。
   `window.toast` 和 `window.modal` 是 vendor/situ-ui.js 提供的，
   这里不动它们。
   ═══════════════════════════════════════════════════════════════════ */


/* ═════════════════════════════════════════════════════════════════
   Spinner — 通用旋转加载图标 (cover an element)
   ═════════════════════════════════════════════════════════════════ */

.sf-spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid currentColor;
  border-radius: 50%;
  border-top-color: transparent;
  animation: sf-spin 700ms linear infinite;
  vertical-align: middle;
}
.sf-spinner--sm { width: 12px; height: 12px; border-width: 1.5px; }
.sf-spinner--lg { width: 28px; height: 28px; border-width: 3px; }

@keyframes sf-spin { to { transform: rotate(360deg); } }

/* Spinner overlay — 覆盖任意元素，元素需要 position:relative */
.sf-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 12px;
  background: rgba(20, 12, 4, 0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  z-index: var(--z-popover, 1000);
  color: var(--aura, #c8912f);
  border-radius: inherit;
  animation: sf-fade-in var(--dur-fast, 200ms) var(--ease, ease);
}
.sf-overlay--light {
  background: rgba(243, 233, 212, 0.78);
  color: var(--aura-deep, #a06a1a);
}
.sf-overlay-label {
  font: 500 12px var(--f-mono, monospace);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.9;
}


/* ═════════════════════════════════════════════════════════════════
   Skeleton — shimmer 占位块
   ═════════════════════════════════════════════════════════════════ */

.sf-skel {
  display: block;
  background:
    linear-gradient(
      90deg,
      rgba(243, 233, 212, 0.06) 0%,
      rgba(243, 233, 212, 0.18) 50%,
      rgba(243, 233, 212, 0.06) 100%
    );
  background-size: 200% 100%;
  border-radius: var(--r-sm, 6px);
  animation: sf-shimmer 1.4s ease-in-out infinite;
  pointer-events: none;
}
.sf-skel--text {
  height: 14px;
  margin: 6px 0;
  border-radius: 3px;
}
.sf-skel--text:nth-child(odd) { width: 92%; }
.sf-skel--text:nth-child(even) { width: 78%; }
.sf-skel--title {
  height: 24px;
  width: 50%;
  margin-bottom: 14px;
}
.sf-skel--card {
  height: 120px;
  border-radius: var(--r-lg, 14px);
}
.sf-skel--avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
}
.sf-skel--button {
  width: 120px;
  height: 36px;
  border-radius: var(--r-md, 10px);
}

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

/* Light variant for parchment / amber pages */
.sf-skel--light {
  background:
    linear-gradient(
      90deg,
      rgba(70, 50, 30, 0.06) 0%,
      rgba(70, 50, 30, 0.16) 50%,
      rgba(70, 50, 30, 0.06) 100%
    );
  background-size: 200% 100%;
}


/* ═════════════════════════════════════════════════════════════════
   Progress bar — 确定性长任务进度
   ═════════════════════════════════════════════════════════════════ */

.sf-progress {
  width: 100%;
  height: 4px;
  background: rgba(243, 233, 212, 0.08);
  border-radius: 999px;
  overflow: hidden;
  position: relative;
}
.sf-progress-bar {
  height: 100%;
  background: var(--aura, #c8912f);
  border-radius: inherit;
  transition: width var(--dur-base, 320ms) var(--ease, ease);
  width: 0%;
}
/* 不确定进度（indeterminate）— 来回滑动 */
.sf-progress--indeterminate .sf-progress-bar {
  width: 35%;
  animation: sf-progress-indet 1.5s ease-in-out infinite;
}
@keyframes sf-progress-indet {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(285%); }
}


/* ═════════════════════════════════════════════════════════════════
   Retry toast — 错误 toast 带 Retry 按钮
   ═════════════════════════════════════════════════════════════════ */

.sf-retry-toast {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.sf-retry-toast .sf-retry-btn {
  background: transparent;
  border: 1px solid currentColor;
  color: inherit;
  padding: 4px 12px;
  font: 500 11px/1 var(--f-mono, monospace);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-radius: var(--r-sm, 6px);
  cursor: pointer;
  transition: background var(--dur-fast, 200ms) ease;
}
.sf-retry-toast .sf-retry-btn:hover {
  background: rgba(255, 255, 255, 0.12);
}
.sf-retry-toast .sf-retry-code {
  font: 10px var(--f-mono, monospace);
  opacity: 0.55;
  letter-spacing: 0.08em;
}


/* ═════════════════════════════════════════════════════════════════
   Banner — 顶部全宽持久横幅 (offline / maintenance)
   ═════════════════════════════════════════════════════════════════ */

.sf-banner {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: calc(var(--z-toast, 9000) - 10);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 10px 16px;
  font: 500 12px var(--f-body, system-ui);
  letter-spacing: 0.04em;
  color: #fff;
  transform: translateY(-100%);
  transition: transform var(--dur-base, 320ms) var(--ease, ease);
  pointer-events: auto;
}
.sf-banner.is-shown { transform: translateY(0); }
.sf-banner--info    { background: linear-gradient(135deg, #4a7ba8, #2c5d8a); }
.sf-banner--warn    { background: linear-gradient(135deg, #c8912f, #a06a1a); color: #fff; }
.sf-banner--offline { background: linear-gradient(135deg, #5d4f3d, #2a2014); }
.sf-banner--error   { background: linear-gradient(135deg, #b54028, #962f1c); }

.sf-banner i { font-size: 14px; opacity: 0.9; }
.sf-banner-dismiss {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.35);
  color: inherit;
  padding: 3px 10px;
  font: 500 10px var(--f-mono, monospace);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-radius: 3px;
  cursor: pointer;
  margin-left: 8px;
}
.sf-banner-dismiss:hover { background: rgba(255, 255, 255, 0.15); }


/* ═════════════════════════════════════════════════════════════════
   Fade-in keyframe (shared)
   ═════════════════════════════════════════════════════════════════ */

@keyframes sf-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}


/* ═════════════════════════════════════════════════════════════════
   prefers-reduced-motion: 关闭所有动画
   ═════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .sf-spinner,
  .sf-skel,
  .sf-progress--indeterminate .sf-progress-bar {
    animation: none;
  }
  .sf-spinner {
    border-top-color: currentColor;
    opacity: 0.7;
  }
}
