/*
 * ss-wait.css — SkrivSikkert's ONE waiting/feedback language (the "wait family").
 * Docs + adoption guide: docs/ss-wait-library.md
 *
 * Four species, one palette (sage fill on calm track — same tokens as the
 * Morten-approved staged-progress bar, chat-messages.css .ss-chat-stage):
 *   1. dots      — short waits ("Sofia taenker")            .ss-wait-dots
 *   2. stage     — long jobs w. stages (ssStagedProgress)   .ss-stage-bar (lives w. surface)
 *   3. skeleton  — cards/panels fetching content            .ss-wait-skel-line
 *   4. busy ring — a button/control working                 .ss-wait-ring / ssWait.busy()
 *
 * Load order contract: this file is linked AFTER every robot stylesheet so the
 * ADAPTER section below wins ties. Adapters restyle the pre-library loader
 * classes (color/tint ONLY — geometry, timing and markup stay untouched) so
 * every legacy loader joins the family without JS changes. New code uses the
 * canonical classes; adapters exist so history converges, and they use doubled
 * class selectors (.x.x) to outrank single-context variant overrides that load
 * earlier (e.g. the email-compose embed skeleton, blod-bolge ~11672).
 *
 * Dark mode: this codebase's dark is [data-theme="dark"] on <html> (manual
 * toggle — NOT prefers-color-scheme). Tokens flip there; adapter dark rules
 * mirror the existing dark overrides they must outrank.
 */

:root {
  --ss-wait-accent: #6E8A7E;                 /* sage FILL (ssu-darkmode canon) */
  --ss-wait-track: rgba(110, 138, 126, 0.15);
  --ss-wait-skel-a: rgba(110, 138, 126, 0.10);
  --ss-wait-skel-b: rgba(110, 138, 126, 0.22);
  /* Cancel/stop affordance for long AI waits (Morten 13/7: "neutral dark/grey" —
     the green BAR stays sage; only the cancel is neutral, never red/cream).
     THREE token sets, one library source, all neutral:
       - outline  (--cancel-ink/-line/-bg)   → skrivebord's .ai-cancel-btn
       - soft fill (--cancel-fill/-hover)     → translator's .st-cancel-btn (was red)
       - strong    (--cancel-strong/-hover/-ink) → chat's send→stop (interrupt a stream) */
  --ss-wait-cancel-ink: #5C5C5E;             /* neutral grey text/icon (outline cancels, e.g. skrivebord) */
  --ss-wait-cancel-line: rgba(60, 60, 62, 0.22);
  --ss-wait-cancel-bg: rgba(60, 60, 62, 0.06);
  /* FILLED cancel buttons (e.g. translator's, was red): a fixed neutral-dark
     fill that stays legible with white text in BOTH themes — so we never flip
     to a light fill that would hide white text. */
  --ss-wait-cancel-fill: #5C5C5E;
  --ss-wait-cancel-fill-hover: #6B6B6E;
  /* STRONG stop (interrupt an in-flight stream, e.g. chat's send→stop): a
     high-contrast INVERTED neutral (near-black on light, near-white on dark) —
     more prominent than the soft mid-grey cancel because interrupting a live
     stream wants a firmer affordance. Still neutral (never red/sage). */
  --ss-wait-cancel-strong: #1d1d1f;
  --ss-wait-cancel-strong-hover: #333333;
  --ss-wait-cancel-strong-ink: #ffffff;
}
[data-theme="dark"] {
  --ss-wait-accent: #7DA893;
  --ss-wait-track: rgba(125, 168, 147, 0.18);
  --ss-wait-skel-a: rgba(125, 168, 147, 0.10);
  --ss-wait-skel-b: rgba(125, 168, 147, 0.24);
  --ss-wait-cancel-ink: #C8C8CC;
  --ss-wait-cancel-line: rgba(232, 232, 236, 0.22);
  --ss-wait-cancel-bg: rgba(232, 232, 236, 0.08);
  --ss-wait-cancel-strong: #e8e8ed;
  --ss-wait-cancel-strong-hover: #ffffff;
  --ss-wait-cancel-strong-ink: #1d1d1f;
}

/* ── Shared keyframes (the family's pulse) ─────────────────────────────── */
@keyframes ss-wait-bounce {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.45; }
  30% { transform: translateY(-4px); opacity: 1; }
}
@keyframes ss-wait-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@keyframes ss-wait-spin {
  to { transform: rotate(360deg); }
}
@keyframes ss-wait-pulse {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 1; }
}

/* ── 1. Dots ───────────────────────────────────────────────────────────── */
.ss-wait-dots {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.ss-wait-dots i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ss-wait-accent);
  animation: ss-wait-bounce 1.4s ease-in-out infinite;
}
.ss-wait-dots i:nth-child(2) { animation-delay: 0.2s; }
.ss-wait-dots i:nth-child(3) { animation-delay: 0.4s; }

/* ── ADAPTER: skrivebordets .gradient-loader(-smart) → dots-arten ──
   Morten-fund 15/7: gb-bundlens tænker-ring lånte --color-primary
   (skrivebordets PINK-RØDE #e24668 — doc-preview-klassens recidiv).
   Valgt erstatning: prikkerne (art 1). Markup er ÉN div — de to
   søskende-prikker males med pseudos så JS aldrig røres. SCOPET til fund-fladen (lock + hamdan-boble): klassenavnet findes også i delte filer (sidebar-chat.css, translator-bundlen) — de flader adopteres i egne runder, aldrig som bleed (hostile r1, ægte fund). */
.loader-backdrop .gradient-loader,
.sk-selection-ai-loading .gradient-loader,
.hamdan-speech-bubble .gradient-loader,
.loader-backdrop .gradient-loader-smart,
.hamdan-speech-bubble .gradient-loader-smart {
  width: 7px;
  height: 7px;
  border: 0;
  border-radius: 50%;
  background: var(--ss-wait-accent);
  animation: ss-wait-bounce 1.4s ease-in-out infinite;
  animation-delay: 0.2s;
  position: relative;
  margin-inline: 12px;
}
.loader-backdrop .gradient-loader::before,
.hamdan-speech-bubble .gradient-loader::before,
.loader-backdrop .gradient-loader::after,
.hamdan-speech-bubble .gradient-loader::after,
.loader-backdrop .gradient-loader-smart::before,
.hamdan-speech-bubble .gradient-loader-smart::before,
.loader-backdrop .gradient-loader-smart::after,
.hamdan-speech-bubble .gradient-loader-smart::after {
  content: "";
  position: absolute;
  top: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ss-wait-accent);
  animation: ss-wait-bounce 1.4s ease-in-out infinite;
}
.loader-backdrop .gradient-loader::before,
.hamdan-speech-bubble .gradient-loader::before,
.loader-backdrop .gradient-loader-smart::before,
.hamdan-speech-bubble .gradient-loader-smart::before {
  left: -12px;
  animation-delay: 0s;
}
.loader-backdrop .gradient-loader::after,
.hamdan-speech-bubble .gradient-loader::after,
.loader-backdrop .gradient-loader-smart::after,
.hamdan-speech-bubble .gradient-loader-smart::after {
  left: 12px;
  animation-delay: 0.4s;
}
@media (prefers-reduced-motion: reduce) {
  .loader-backdrop .gradient-loader,
.sk-selection-ai-loading .gradient-loader,
  .hamdan-speech-bubble .gradient-loader,
  .loader-backdrop .gradient-loader-smart,
  .hamdan-speech-bubble .gradient-loader-smart,
  .loader-backdrop .gradient-loader::before,
  .hamdan-speech-bubble .gradient-loader::before,
  .loader-backdrop .gradient-loader::after,
  .hamdan-speech-bubble .gradient-loader::after,
  .loader-backdrop .gradient-loader-smart::before,
  .hamdan-speech-bubble .gradient-loader-smart::before,
  .loader-backdrop .gradient-loader-smart::after,
  .hamdan-speech-bubble .gradient-loader-smart::after {
    animation: none;
    opacity: 0.7;
  }
}

/* ── 3. Skeleton ───────────────────────────────────────────────────────── */
.ss-wait-skel {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ss-wait-skel-line {
  height: 13px;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
  animation: ss-wait-shimmer 1.5s ease-in-out infinite;
}
.ss-wait-skel-line:nth-child(2) { width: 78%; }
.ss-wait-skel-line:nth-child(3) { width: 56%; }

/* ── 4. Busy ring ──────────────────────────────────────────────────────── */
.ss-wait-ring {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
  border-radius: 50%;
  animation: ss-wait-spin 0.7s linear infinite;
  flex-shrink: 0;
}
/* On a sage/filled control the ring is white-on-accent instead. */
.ss-wait-ring--onaccent {
  border-color: rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
}
/* Soft press feedback for any actionable control. */
.ss-wait-press { transition: transform 0.12s ease; }
.ss-wait-press:active { transform: scale(0.96); }

/* ══ ADAPTERS — legacy loaders join the family (color/tint only) ════════ */

/* Sofia taenker (chat-renderer.js typing bubble) */
.typing-dots.typing-dots span { background: var(--ss-wait-accent); }
[data-theme="dark"] .typing-dots.typing-dots span { background: var(--ss-wait-accent); }

/* Start-screen signal shimmer (sofia-signals.js) */
.sofia-signal-shimmer.sofia-signal-shimmer {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}
[data-theme="dark"] .sofia-signal-shimmer.sofia-signal-shimmer {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}

/* Calm letter skeleton (sofia-signals.js calm compose) */
.calm-letter--loading .calm-skel-line.calm-skel-line {
  background-color: var(--ss-wait-skel-a);
  background-image: linear-gradient(90deg, rgba(110, 138, 126, 0) 0%, var(--ss-wait-skel-b) 50%, rgba(110, 138, 126, 0) 100%);
}
[data-theme="dark"] .calm-letter--loading .calm-skel-line.calm-skel-line {
  background-color: var(--ss-wait-skel-a);
  background-image: linear-gradient(90deg, rgba(125, 168, 147, 0) 0%, var(--ss-wait-skel-b) 50%, rgba(125, 168, 147, 0) 100%);
}

/* Conversation-open skeleton bubbles (chat-conversations.js) */
.chat-skeleton-avatar.chat-skeleton-avatar,
.chat-skeleton-line.chat-skeleton-line {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}
[data-theme="dark"] .chat-skeleton-avatar.chat-skeleton-avatar,
[data-theme="dark"] .chat-skeleton-line.chat-skeleton-line {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}

/* History drawer loading bars (chat-history-drawer.js) */
.chd-loading-bar.chd-loading-bar { background: var(--ss-wait-track); }
[data-theme="dark"] .chd-loading-bar.chd-loading-bar { background: var(--ss-wait-track); }

/* Embed cards + modal skeleton (chat-embeds.js / embeds/embed.css) */
.ss-embed-card-spinner.ss-embed-card-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}
[data-theme="dark"] .ss-embed-card-spinner.ss-embed-card-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}
.ss-embed-skeleton-label.ss-embed-skeleton-label,
.ss-embed-skeleton-value.ss-embed-skeleton-value,
.ss-embed-skeleton-line.ss-embed-skeleton-line,
.ss-embed-skeleton-btn.ss-embed-skeleton-btn,
.ss-embed-skeleton-chip.ss-embed-skeleton-chip,
.ss-embed-skeleton-ask.ss-embed-skeleton-ask {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}
[data-theme="dark"] .ss-embed-skeleton-label.ss-embed-skeleton-label,
[data-theme="dark"] .ss-embed-skeleton-value.ss-embed-skeleton-value,
[data-theme="dark"] .ss-embed-skeleton-line.ss-embed-skeleton-line,
[data-theme="dark"] .ss-embed-skeleton-btn.ss-embed-skeleton-btn,
[data-theme="dark"] .ss-embed-skeleton-chip.ss-embed-skeleton-chip,
[data-theme="dark"] .ss-embed-skeleton-ask.ss-embed-skeleton-ask {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}

/* Visualization loading (chat-visualizations.js) */
.viz-loading-spinner.viz-loading-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}
[data-theme="dark"] .viz-loading-spinner.viz-loading-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}

/* Voice mode "connecting" (voice-mode.js) */
.ssv-spinner.ssv-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}
[data-theme="dark"] .ssv-spinner.ssv-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}

/* PDF picker/chunk-flow mini-card shimmer (chat-pdf-reader.js + chat-chunk-flow.js) */
.ss-pdf-mini.is-shimmer.is-shimmer {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}
[data-theme="dark"] .ss-pdf-mini.is-shimmer.is-shimmer {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}

/* ── Chat runde 7 (15/7): lydfil-transskriberingens vente-tilstand.
      Spinneren lånte --color-primary = PINK #e24668 (off-palette-detektorens
      klasse: doc-preview-spinneren/rose-ringens søster, chat-transcribe.css)
      og «Transskriberer…»-badgen var pink tekst på pink-tint. Ventetilstand →
      sage; is-done (grøn) og is-error (rød) er ÆGTE semantik og røres ikke.
      Status-ink = chats egen sage-tekst-idiom (talk-mode-labelens
      --sage-dark); dark-ink = accent (matcher talk-mode dark). Legacy-spec:
      spinner (0,1,0) uden dark-regel; status light (0,2,0) / dark (0,3,0) →
      (0,3,0)/(0,4,0) her. ── */
.chat-audio-spinner.chat-audio-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}
[data-theme="dark"] .chat-audio-spinner.chat-audio-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}
.chat-audio-status.chat-audio-status.is-transcribing {
  color: var(--sage-dark, #4A7A68);
  background: var(--ss-wait-track);
}
[data-theme="dark"] .chat-audio-status.chat-audio-status.is-transcribing {
  color: var(--ss-wait-accent);
  background: var(--ss-wait-track);
}

/* ══ EMAIL ROBOT ADAPTERS (/email/) ═════════════════════════════════════
   Only the loaders that were GREY / off-family are pulled in here. The many
   /email/ loaders already on sage (calm-spin, cl-refresh-spin, efk-*, ptr-spin,
   todo-rescan-spin, calmShimmer, sofia-shimmer, email-reply-shimmer) are left
   as-is — they already read as the family. Dark twins only where a legacy
   [data-theme="dark"] rule exists to outrank; no !important anywhere on these
   targets (verified), so doubled-class wins cleanly. */

/* Bulk-select progress spinner (email-list.css) — no legacy dark rule, tokens flip */
.email-bulk-progress-spinner.email-bulk-progress-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}

/* Search spinner (email-base.css; dark at email-darkmode.css) */
.email-search__spinner.email-search__spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}
[data-theme="dark"] .email-search__spinner.email-search__spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}

/* Attachment download ring (email-reader.css ::after) — no legacy dark rule */
.email-attachment-item.is-downloading.is-downloading::after,
.email-attachment-thumb-download.is-downloading.is-downloading::after,
.email-attachment-download-btn.is-downloading.is-downloading::after,
.email-attachment-pdf-header.is-downloading.is-downloading::after {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}

/* Toolbar skeleton (email-base.css; dark at email-darkmode.css) */
.toolbar-sk-btn.toolbar-sk-btn,
.toolbar-sk-search.toolbar-sk-search,
.toolbar-sk-icon.toolbar-sk-icon,
.sk-skeleton.sk-skeleton {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}
[data-theme="dark"] .toolbar-sk-btn.toolbar-sk-btn,
[data-theme="dark"] .toolbar-sk-search.toolbar-sk-search,
[data-theme="dark"] .toolbar-sk-icon.toolbar-sk-icon,
[data-theme="dark"] .sk-skeleton.sk-skeleton {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}

/* List skeleton avatar + lines (email-base.css solid + opacity pulse; dark at email-darkmode.css) */
.email-skeleton-avatar.email-skeleton-avatar,
.email-skeleton-line.email-skeleton-line {
  background: var(--ss-wait-skel-b);
}
[data-theme="dark"] .email-skeleton-avatar.email-skeleton-avatar,
[data-theme="dark"] .email-skeleton-line.email-skeleton-line {
  background: var(--ss-wait-skel-b);
}

/* AI shimmer (email-ai.css; TWO legacy dark rules — 0,3,0 beats both) */
.email-ai-shimmer.email-ai-shimmer {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}
[data-theme="dark"] .email-ai-shimmer.email-ai-shimmer {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}

/* Quick-summary shimmer lines (email-ai-summary-card.css; dark in same file) */
.email-quick-summary-shimmer-line.email-quick-summary-shimmer-line {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}
[data-theme="dark"] .email-quick-summary-shimmer-line.email-quick-summary-shimmer-line {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}

/* ══ SKRIVEBORD ROBOT ADAPTERS (/skrivebord/) ══════════════════════════
   Morten 13/7: the three long-wait AI robots (chat, skrivebord, translator)
   must feel the same during a long generation. The green BAR is already shared
   (ssStagedProgress). Here we pull skrivebord's OWN AI-wait loader + its
   off-family spinners onto the family: the loading bar/icon were SLATE-BLUE
   (rgba(74,85,104)) / cream, the correction-explanation shimmer TAUPE, the doc
   spinner PINK (--color-primary). The cancel button goes NEUTRAL grey (Morten's
   pick) to match chat's .chat-send-btn.is-stop — the bar stays green, only the
   cancel is neutral. Verified 0 !important on these targets → doubled-class wins.
   Left untouched (already sage / context-correct): calm-kladde-spin, clean-spin,
   ssStagedProgress bar, and all mic/tts/audio/stt state loaders. */

/* AI-wait icon (slate circle → sage) */
.ai-loading-icon.ai-loading-icon {
  background: linear-gradient(135deg, var(--ss-wait-skel-b), var(--ss-wait-skel-a));
}
[data-theme="dark"] .ai-loading-icon.ai-loading-icon {
  background: linear-gradient(135deg, var(--ss-wait-skel-b), var(--ss-wait-skel-a));
}

/* AI-wait bar = track + fill, like the stage-bar (slate/grey → sage) */
.ai-loading-bar.ai-loading-bar { background: var(--ss-wait-track); }
.ai-loading-bar-fill.ai-loading-bar-fill { background: var(--ss-wait-accent); }
[data-theme="dark"] .ai-loading-bar.ai-loading-bar { background: var(--ss-wait-track); }
[data-theme="dark"] .ai-loading-bar-fill.ai-loading-bar-fill { background: var(--ss-wait-accent); }

/* AI-wait cancel button → NEUTRAL grey (Morten 13/7; matches chat's is-stop) */
.ai-cancel-btn.ai-cancel-btn {
  color: var(--ss-wait-cancel-ink);
  border-color: var(--ss-wait-cancel-line);
  background: var(--ss-wait-cancel-bg);
}
[data-theme="dark"] .ai-cancel-btn.ai-cancel-btn {
  color: var(--ss-wait-cancel-ink);
  border-color: var(--ss-wait-cancel-line);
  background: var(--ss-wait-cancel-bg);
}

/* Correction-explanation shimmer (taupe → sage) */
.calm-corr-card-explanation--loading.calm-corr-card-explanation--loading {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}
[data-theme="dark"] .calm-corr-card-explanation--loading.calm-corr-card-explanation--loading {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 200% 100%;
}

/* Doc-preview spinner (grey ring + PINK top → sage) */
.doc-preview-spinner.doc-preview-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}
[data-theme="dark"] .doc-preview-spinner.doc-preview-spinner {
  border-color: var(--ss-wait-track);
  border-top-color: var(--ss-wait-accent);
}

/* ══ TRANSLATOR ROBOT ADAPTERS (/oversaettelse/, /translator/) ═══════════
   Translator's CSS is a minified, un-rebuildable bundle → the family joins as
   an OVERRIDE layer (ss-wait.css links AFTER the bundle). Its long-wait bar
   already uses ssStagedProgress (sage). Only the GREY loaders are pulled in:
   the typing dots (.st-dot, --color-text-tertiary #8f8e8a) and the skeleton
   shimmer (.st-skeleton-line, grey --color-border/--color-bg gradient). No
   cancel loader in translator. Mic/rec/tts state loaders left untouched. */

/* Translator typing dots (grey → sage) */
.st-dot.st-dot { background: var(--ss-wait-accent); }
[data-theme="dark"] .st-dot.st-dot { background: var(--ss-wait-accent); }

/* Translator skeleton shimmer (grey gradient → sage) */
.st-skeleton-line.st-skeleton-line {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 800px 100%;
}
[data-theme="dark"] .st-skeleton-line.st-skeleton-line {
  background: linear-gradient(90deg, var(--ss-wait-skel-a) 25%, var(--ss-wait-skel-b) 50%, var(--ss-wait-skel-a) 75%);
  background-size: 800px 100%;
}

/* Translator cancel button: RED → NEUTRAL (Morten 13/7 — uniform w. chat +
   skrivebord). The legacy rule is inline !important in index.php, so the
   adapter needs !important + doubled-class (dark = 0,3,0 to beat the inline
   [data-theme=dark] .st-cancel-btn 0,2,0). White text forced for contrast on
   the neutral fill regardless of the base button's color. */
.st-cancel-btn.st-cancel-btn {
  background: var(--ss-wait-cancel-fill) !important;
  color: #fff !important;
}
.st-cancel-btn.st-cancel-btn:hover:not(:disabled) {
  background: var(--ss-wait-cancel-fill-hover) !important;
}
[data-theme="dark"] .st-cancel-btn.st-cancel-btn {
  background: var(--ss-wait-cancel-fill) !important;
  color: #fff !important;
}
[data-theme="dark"] .st-cancel-btn.st-cancel-btn:hover:not(:disabled) {
  background: var(--ss-wait-cancel-fill-hover) !important;
}

/* NOTE deliberately NOT adapted:
   - .chat-upload-spinner (chat-files.js): lives INSIDE the sage send button,
     white-on-accent ring = already the family's --onaccent variant.
   - .ss-play--loading::after (TTS, stt-tts-ui.css): same — white ring on the
     sage play control.
   - .ss-chat-stage / .ss-stage-bar: IS the canon this family grew from.
   - /email/ loaders already on sage (calm-spin, cl-refresh-spin, efk-*,
     ptr-spin, todo-*, calmShimmer, sofia-shimmer, email-reply-shimmer): left
     untouched — already the family look. */

/* ── Reduced motion: the whole family goes still ───────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .ss-wait-dots i,
  .ss-wait-skel-line,
  .ss-wait-ring,
  .ss-wait-press { animation: none !important; transition: none !important; }
  /* Adapted legacy loaders go still too — and the calm letter skeleton keeps
     its legacy contract (flat color, no gradient): the adapter's 0,3,0 beats
     blod-bolge's reduced-motion background-image:none (0,2,0), so restate it
     here at adapter specificity (lens MED 12/7). */
  .chat-audio-spinner.chat-audio-spinner,
  .typing-dots.typing-dots span,
  .sofia-signal-shimmer.sofia-signal-shimmer,
  .calm-letter--loading .calm-skel-line.calm-skel-line,
  .chat-skeleton-avatar.chat-skeleton-avatar,
  .chat-skeleton-line.chat-skeleton-line,
  .chd-loading-bar.chd-loading-bar,
  .ss-embed-card-spinner.ss-embed-card-spinner,
  .ss-embed-skeleton-label.ss-embed-skeleton-label,
  .ss-embed-skeleton-value.ss-embed-skeleton-value,
  .ss-embed-skeleton-line.ss-embed-skeleton-line,
  .ss-embed-skeleton-btn.ss-embed-skeleton-btn,
  .ss-embed-skeleton-chip.ss-embed-skeleton-chip,
  .ss-embed-skeleton-ask.ss-embed-skeleton-ask,
  .viz-loading-spinner.viz-loading-spinner,
  .ssv-spinner.ssv-spinner,
  .ss-pdf-mini.is-shimmer.is-shimmer,
  .email-bulk-progress-spinner.email-bulk-progress-spinner,
  .email-search__spinner.email-search__spinner,
  .toolbar-sk-btn.toolbar-sk-btn,
  .toolbar-sk-search.toolbar-sk-search,
  .toolbar-sk-icon.toolbar-sk-icon,
  .sk-skeleton.sk-skeleton,
  .email-skeleton-avatar.email-skeleton-avatar,
  .email-skeleton-line.email-skeleton-line,
  .email-ai-shimmer.email-ai-shimmer,
  .email-quick-summary-shimmer-line.email-quick-summary-shimmer-line,
  .email-attachment-item.is-downloading.is-downloading::after,
  .email-attachment-thumb-download.is-downloading.is-downloading::after,
  .email-attachment-download-btn.is-downloading.is-downloading::after,
  .email-attachment-pdf-header.is-downloading.is-downloading::after,
  .ai-loading-icon.ai-loading-icon,
  .ai-loading-bar-fill.ai-loading-bar-fill,
  .calm-corr-card-explanation--loading.calm-corr-card-explanation--loading,
  .doc-preview-spinner.doc-preview-spinner,
  .st-dot.st-dot,
  .st-skeleton-line.st-skeleton-line { animation: none !important; }
  .calm-letter--loading .calm-skel-line.calm-skel-line { background-image: none; }
  .sofia-signal-shimmer.sofia-signal-shimmer,
  .chat-skeleton-avatar.chat-skeleton-avatar,
  .chat-skeleton-line.chat-skeleton-line,
  .ss-embed-skeleton-label.ss-embed-skeleton-label,
  .ss-embed-skeleton-value.ss-embed-skeleton-value,
  .ss-embed-skeleton-line.ss-embed-skeleton-line,
  .ss-embed-skeleton-btn.ss-embed-skeleton-btn,
  .ss-embed-skeleton-chip.ss-embed-skeleton-chip,
  .ss-embed-skeleton-ask.ss-embed-skeleton-ask,
  .ss-pdf-mini.is-shimmer.is-shimmer,
  .toolbar-sk-btn.toolbar-sk-btn,
  .toolbar-sk-search.toolbar-sk-search,
  .toolbar-sk-icon.toolbar-sk-icon,
  .sk-skeleton.sk-skeleton,
  .email-ai-shimmer.email-ai-shimmer,
  .email-quick-summary-shimmer-line.email-quick-summary-shimmer-line,
  .st-skeleton-line.st-skeleton-line { background: var(--ss-wait-skel-a); }
}


/* runde 6: markerings-pillen (sk-selection-ai-loading) taler samme prik-sprog */
.sk-selection-ai-loading .gradient-loader::before,
.sk-selection-ai-loading .gradient-loader::after {
  content: "";
  position: absolute;
  top: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ss-wait-accent);
  animation: ss-wait-bounce 1.4s ease-in-out infinite;
}
.sk-selection-ai-loading .gradient-loader::before { left: -12px; animation-delay: 0s; }
.sk-selection-ai-loading .gradient-loader::after { left: 12px; animation-delay: 0.4s; }
@media (prefers-reduced-motion: reduce) {
  .sk-selection-ai-loading .gradient-loader,
  .sk-selection-ai-loading .gradient-loader::before,
  .sk-selection-ai-loading .gradient-loader::after { animation: none; opacity: 0.7; }
}
