/* =====================================================================
   Loading / progress component (HANDOFF-loading.md).
   Two presets share one vocabulary:
     • .kwl-splash  — full-viewport branded overlay (login / OAuth redirect)
     • .kwl-steps   — deliberate step-progress dialog (install / governance),
                      reuses the .dlg base (dialog.css)
   Plus a button-pending helper (.is-pending) usable on any button.

   Token-driven: every colour is a --kw-* token (tokens.css); themed via
   html.dark (public) / html.light (admin). Direction-agnostic — logical
   properties only, so it mirrors under <html dir="rtl"> (see test_rtl_layout).
   The orb is self-contained here (there is no .icon-orb primitive — same as
   .dlg__orb in dialog.css).
   ===================================================================== */

/* ---------- shared: orbital spinner ---------- */
.kwl-orbit { position: relative; flex-shrink: 0; width: 100%; height: 100%; display: grid; place-items: center; }
.kwl-orbit__ring { position: absolute; inset: 0; border-radius: 50%; border: 1.5px solid transparent; }
.kwl-orbit__ring--1 { border-block-start-color: var(--kw-electric-indigo); border-inline-end-color: rgba(77,96,251,0.35); animation: kwl-spin 1s linear infinite; }
.kwl-orbit__ring--2 { inset: 16%; border-block-start-color: var(--kw-soft-lavender); border-inline-start-color: rgba(221,214,251,0.3); animation: kwl-spin 1.5s linear infinite reverse; }
.kwl-orbit__core { width: 30%; height: 30%; border-radius: 50%; background: var(--kw-electric-indigo); box-shadow: 0 0 18px 2px rgba(77,96,251,0.7); animation: kwl-pulse 1.4s ease-in-out infinite; }
@keyframes kwl-spin { to { transform: rotate(360deg); } }
@keyframes kwl-pulse { 0%,100% { opacity: .55; transform: scale(.82); } 50% { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .kwl-orbit__ring--1, .kwl-orbit__ring--2 { animation-duration: 2.4s; }
  .kwl-orbit__core { animation: none; opacity: .9; }
}

/* ---------- self-contained icon orb (no .icon-orb primitive) ---------- */
.kwl-orb {
  position: relative; display: grid; place-items: center; overflow: hidden; flex-shrink: 0;
  border-radius: var(--kw-radius-md);
  background: var(--kw-glass-fill); border: 1px solid var(--kw-glass-stroke); color: #fff;
}
.kwl-orb::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(135deg, rgba(221,214,251,0.45), rgba(221,214,251,0));
}
.kwl-orb > * { position: relative; }  /* glyph rides above the sheen */
.kwl-orb svg { display: block; }
html.dark .kwl-orb { box-shadow: var(--kw-glow-glass); }
/* light/admin: solid brand blue + white glyph (glass is too pale on white) */
html.light .kwl-orb { background: var(--kw-blue); border-color: var(--kw-blue); }
html.light .kwl-orb::before { background: linear-gradient(135deg, rgba(255,255,255,0.28), rgba(255,255,255,0)); }
/* success orb: SOLID success-green fill carries a WHITE glyph in both themes.
   Per the brand icon rule colour comes from the saturated container, never the
   glyph — a pale tint (the old recipe) can't carry the white stroke loading.js
   sets, so the icon vanished. Error/fail orb stays gold below. */
.kwl-orb--success { background: var(--kw-teal); border-color: var(--kw-teal); box-shadow: 0 6px 16px -6px rgba(43,182,115,0.55); }
.kwl-orb--success::before { background: linear-gradient(135deg, rgba(255,255,255,0.4), rgba(255,255,255,0)); }
.kwl-orb--success > * { color: #fff; stroke: #fff; }
html.light .kwl-orb--success { background: var(--kw-teal); border-color: var(--kw-teal); box-shadow: 0 6px 16px -6px rgba(43,182,115,0.55); }
html.light .kwl-orb--success > * { color: #fff; stroke: #fff; }
.kwl-orb--gold { background: rgba(253,202,19,0.16); border-color: rgba(253,202,19,0.45); box-shadow: inset 0 0 22px rgba(253,202,19,0.18); }
.kwl-orb--gold > * { color: var(--kw-signal-gold); }
html.light .kwl-orb--gold { background: #FEF6DC; border-color: #F6E0A0; box-shadow: none; }
html.light .kwl-orb--gold > * { color: var(--kw-yellow-ink); }

/* ============================================================
   PRESET 1 — SPLASH (login / OAuth redirect)
   Shown the instant the user clicks, before the browser navigates.
   ============================================================ */
.kwl-splash {
  position: fixed; inset: 0; z-index: 9000; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 30px;
  background: var(--kw-deep-space); color: #fff; text-align: center;
  opacity: 0; transition: opacity 220ms ease; overflow: hidden;
}
.kwl-splash.is-in { opacity: 1; }
/* reuse the brand backdrop motifs (positioned via inline styles in loading.js) */
.kwl-splash__bg { position: absolute; inset: 0; pointer-events: none; }
.kwl-splash__ring { position: absolute; border-radius: 50%; border: 1px dashed rgba(77,96,251,0.35); }
.kwl-splash__glow { position: absolute; border-radius: 50%; filter: blur(120px); opacity: .5; }
.kwl-splash__inner { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 26px; padding: 0 24px; }
/* entrance: the whole overlay fades in via .is-in. Individual items keep their
   natural (visible) state — no per-item opacity animation, so content is never
   stuck hidden in any context. The orbit spinner + dots + bar still animate. */
.kwl-splash__logo { height: 30px; }
.kwl-splash__orbit { width: 76px; height: 76px; }
.kwl-splash__title { font-family: var(--kw-font-headline); font-weight: 600; font-size: 22px; letter-spacing: -0.02em; margin: 0; }
.kwl-splash__sub { font-family: var(--kw-font-mono); font-size: 12.5px; color: var(--kw-muted-lavender); margin: 9px 0 0; min-height: 1em; }
.kwl-splash__dots::after { content: ""; animation: kwl-dots 1.4s steps(1,end) infinite; }
@keyframes kwl-dots { 0%{content:"";} 25%{content:"·";} 50%{content:"··";} 75%{content:"···";} }
/* thin top progress shimmer for the redirect wait */
.kwl-splash__bar { position: absolute; inset-block-start: 0; inset-inline: 0; height: 3px; overflow: hidden; z-index: 3; background: rgba(77,96,251,0.16); }
.kwl-splash__bar::before { content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; width: 40%; background: linear-gradient(90deg, transparent, var(--kw-electric-indigo), transparent); transform: translateX(-120%); animation: kwl-sweep 1.25s ease-in-out infinite; }
@keyframes kwl-sweep { 0%{ transform: translateX(-120%); } 100%{ transform: translateX(350%); } }
@media (prefers-reduced-motion: reduce) {
  .kwl-splash__logo, .kwl-splash__orbit, .kwl-splash__text { animation: none; opacity: 1; }
  .kwl-splash__bar::before { animation-duration: 3s; }
}

/* ============================================================
   PRESET 2 — STEPS dialog (install / governance action)
   Deliberate, minimum-dwell, trust-building. Reuses the .dlg base.
   ============================================================ */
.kwl-steps__head { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; }
.kwl-steps__orbit { width: 44px; height: 44px; }
.kwl-steps__orbit svg { width: 22px; height: 22px; }
.kwl-steps__titles h3 { font-size: 18px; font-weight: 700; letter-spacing: -0.015em; margin: 0; color: var(--kw-fg); }
.kwl-steps__titles p { font-size: 13px; color: var(--kw-fg-muted); margin: 2px 0 0; }

.kwl-steps__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.kwl-step { display: flex; align-items: center; gap: 12px; padding: 11px 12px; border-radius: var(--kw-radius-md); font-size: 14px; color: var(--kw-fg-subtle); transition: background 180ms, color 180ms; }
.kwl-step__icon { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; flex-shrink: 0; position: relative; border: 1.5px solid var(--kw-border-color); }
.kwl-step__icon .kwl-step__glyph { grid-area: 1 / 1; display: grid; place-items: center; line-height: 0; }
.kwl-step__icon svg { width: 14px; height: 14px; display: block; }
.kwl-step__icon .kwl-mini { position: absolute; inset: -1.5px; border-radius: 50%; border: 1.5px solid transparent; border-top-color: var(--kw-blue); animation: kwl-spin .8s linear infinite; display: none; }
.kwl-step__label { flex: 1; }

/* pending (current) step */
.kwl-step.is-active { color: var(--kw-fg); background: var(--kw-bg-subtle); }
html.dark .kwl-step.is-active { background: rgba(77,96,251,0.10); color: #fff; }
.kwl-step.is-active .kwl-step__icon { border-color: var(--kw-blue); }
.kwl-step.is-active .kwl-mini { display: block; }

/* done step */
.kwl-step.is-done { color: var(--kw-fg-muted); }
.kwl-step.is-done .kwl-step__icon { border-color: var(--kw-teal); background: var(--kw-teal); }
.kwl-step.is-done .kwl-step__icon svg { color: #fff; stroke: #fff; }

/* success footer state */
.kwl-steps__done { display: none; flex-direction: column; align-items: center; text-align: center; gap: 6px; padding: 8px 0 4px; }
.kwl-steps__done.is-shown { display: flex; }
.kwl-steps__done-orb { width: 52px; height: 52px; margin-bottom: 6px; }
.kwl-steps__done-orb svg { width: 28px; height: 28px; }
.kwl-steps__done h3 { font-size: 19px; font-weight: 700; margin: 0; color: var(--kw-fg); }
.kwl-steps__done p { font-size: 13.5px; color: var(--kw-fg-muted); margin: 2px 0 0; max-width: 340px; }
.kwl-steps__foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 22px; }
/* footer uses the global .kw-btn-* variants — make them inline (auto width) */
.kwl-steps__foot .kw-btn-primary, .kwl-steps__foot .kw-btn-secondary { width: auto; min-width: 0; font-size: 14px; padding: 10px 16px; }

/* progress meter under the steps */
.kwl-steps__meter { height: 4px; border-radius: 999px; background: var(--kw-bg-subtle); overflow: hidden; margin-top: 18px; }
html.dark .kwl-steps__meter { background: rgba(255,255,255,0.08); }
.kwl-steps__meter span { display: block; height: 100%; width: 0%; border-radius: 999px; background: linear-gradient(90deg, var(--kw-blue), var(--kw-electric-indigo)); transition: width 420ms ease; }

/* ---------- button pending helper (lowest-tier feedback, reusable) ----------
   Class-agnostic so it works on the brand .kw-btn-* buttons AND the legacy
   slate policy-editor buttons. Toggled by KWLoading.button(el, on). */
.is-pending { position: relative; color: transparent !important; pointer-events: none; }
.is-pending::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 16px; height: 16px;
  border-radius: 50%; border: 2px solid currentColor; border-top-color: transparent; opacity: .9;
  animation: kwl-spin .7s linear infinite; color: #fff;
}
/* secondary/ghost buttons sit on a light surface — give the spinner contrast */
.kw-btn-secondary.is-pending::after { color: var(--kw-blue); }
html.dark .kw-btn-secondary.is-pending::after { color: #fff; }
.kw-btn-gold.is-pending::after { color: #2A1E00; }
